I have imported ngbModal module fron ng2bootstrap now i am trying to open modal window and load the current component content into modal body. what is the correct approach to implement ?
search.components.ts
import { Component, OnInit,Pipe, PipeTransform, EventEmitter,Input, Output,OnChanges, SimpleChanges } from '#angular/core';
import {GtConfig} from '#angular-generic-table/core';
import {NgbModal} from '#ng-bootstrap/ng-bootstrap';
import * as io from 'socket.io-client';
#Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css'],
})
export class DetailComponent implements OnChanges{
constructor(private detailService: DetailService,private ngbModal: NgbModal) {};
ngOnInit(){
this.secondConfigObject = {
settings: this.getBaseSettings(),
fields: this.getBaseFields(),
data: []
};
})
}
rowData(event) {
console.log('Event',event);
this.detailService.changeChart(event);
}
execModal(evt){
const modalReg = this.ngbModal.open(Component);
}
}
Related
I am trying to make a dialog box in Angular, but the dialog is not been displayed in the centre, only as a vertical white rectangle to the left.
I will include an image depicting the exact problem: screenshot of the page.
I have included entry components in my appmodule.ts file
There are no errors while compiling it.
Header component.ts file :
import { Component, OnInit } from '#angular/core';
import { MatDialog, MatDialogRef } from '#angular/material';
import { LoginComponent } from '../login/login.component';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
constructor(public dialog: MatDialog ) { }
ngOnInit() {
}
openLoginForm() {
this.dialog.open(LoginComponent, {width: '500px', height: '450px'});
}
}
add LoginComponent in entrycomponents array in module.
like this.
entryComponents: [LoginComponent]
I need to sidebar component function in sidebar.
my header component
import { Component, OnInit, Input,ViewChild } from '#angular/core';
import { SidebarComponent } from '../sidebar/sidebar.component';
#ViewChild(SidebarComponent) SidebarComponent;
ngOnInit() {
this.SidebarComponent.testFunction();
}
sidebar component
testFunction() {
console.log('value');
}
I added an essential code block for the understanding purpose. when I use the above code error said,
ERROR TypeError: Cannot read property 'testFunction' of undefined
at HeaderComponent.push../src/app/layout/components/header/header.component.ts.HeaderComponent.ngOnInit (header.component.ts:57)
can u help me to fix this issue?
call it after child view is initialized.
#ViewChild(SidebarComponent) sidebarComponent: SidebarComponent;
ngAfterViewInit() {
this.sidebarComponent.testFunction();
}
For sharing of functions in Angular, it is better to use a service and call it's functions in both of the components.
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root',
})
export class SharedService {
constructor() { }
sharedFunction(){
console.log('here');
}
}
And in both of components, component1:
import { SharedService } from '../shared.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: '.....',
templateUrl: '.......',
styleUrls: ['........']
})
export class Component1 implements OnInit{
constructor(private sharedService: SharedService) { }
ngOnInit() {
this.sharedService.sharedFunction();
}
}
component2:
import { SharedService } from '../shared.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: '.....',
templateUrl: '.......',
styleUrls: ['........']
})
export class Component2 implements OnInit{
constructor(private sharedService: SharedService) { }
ngOnInit() {
this.sharedService.sharedFunction();
}
}
Could be done using a service. For illustration purpose let's call it HeaderAndSidebarService:
Filename: header-and-sidebar.service.ts
#import { Injectable } from "#angular/core";
#Injectable()
export class HeaderAndSideBarService {
public testFunction() {
console.log('value');
}
}
To use the service, provide it within both header and sidebar component:
import { Component, OnInit, Input,ViewChild } from '#angular/core';
import { HeaderAndSideBarService } from "./header-and-sidebar.service";
#Component({
...,
providers: [HeaderAndSideBarService]
})
export class HeaderComponent {
constructor(private service: HeaderAndSideBarService ) { }
ngOnInit() {
this.service.testFunction();
}
}
I implemented a dynamic theme switcher (with tutorial) in my angular app. It work's but when I reload website, the choice is not remembered.
I read about localStorage and i will use it but still doesn't work because I don't know how "where" I should get data from this localStorage, that the choice of the theme will be remembered when I reload the page.
I have this code:
theme.service.ts new version
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs/Subject';
#Injectable()
export class ThemeService {
private _themeDark: Subject<boolean> = new Subject<boolean>();
isDarkFunction() {
let value = localStorage.getItem('isDark');
this._themeDark.next(value);
return this._themeDark.asObservable();
}
isThemeDark = this.isDarkFunction();
setDarkTheme(isThemeDark: boolean) {
this._themeDark.next(isThemeDark);
localStorage.setItem('isDark', JSON.stringify(isThemeDark));
}
}
navbar.component.html
<div class="container-fluid switcher-container">
<mat-slide-toggle [checked]="isThemeDark | async" (change)="toggleDarkTheme($event.checked)">Dark theme</mat-slide-toggle>
</div>
navbar.component.ts
import { Component, OnInit } from '#angular/core';
import { ThemeService } from '../services/theme.service';
import { Observable } from 'rxjs/Observable';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
isThemeDark: Observable<boolean>;
constructor(
private themeService: ThemeService) { }
ngOnInit() {
this.isThemeDark = this.themeService.isThemeDark;
}
toggleDarkTheme(checked: boolean) {
this.themeService.setDarkTheme(checked);
}
}
app.component.ts
import { Component, OnInit } from '#angular/core';
import { Observable } from "rxjs/Observable";
import { ThemeService } from "./services/theme.service";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
providers: [ThemeService]
})
export class AppComponent implements OnInit {
isThemeDark: Observable<boolean>;
constructor(
public themeService: ThemeService) {
}
ngOnInit() {
this.isThemeDark = this.themeService.isThemeDark;
}
}
Please help,
Regards
You might write something like the following in theme.service.ts.
I don't know if it will run flawlessly as is but the idea is to read from localstorage in isThemeDark().
isThemeDark() {
let value = localStorage.getItem('isDark');
this._themeDark.next(value);
return this._themeDark.asObservable();
}
I think it's because you when you do localStorage.getItem('isDark') the result is a string, not a boolean. Maybe try:
let value = JSON.parse(localStorage.getItem('isDark')) === true;
Also check manually if the localstorage is kept after a refresh. Some browsers have a setting to clear everything on refresh.
My project structure:
app.component.ts:
import { Component } from "#angular/core"
import { Todo } from './components/shared/todo.model'
import { todos } from "./components/shared/todo.data"
import {TodoService} from "./components/shared/todoService"
import {TodoService} from "./components/shared/todoService";
#Component({
moduleId: module.id,
selector: "app",
templateUrl: "app.component.html",
styleUrls: ['app.component.css'],
providers: [TodoService]
})
export class AppComponent {
title:string = "Angular 2Do";
}
todo-form.component.ts:
import {Component, Output, EventEmitter} from "#angular/core";
import {Todo} from "../shared/todo.model";
import {TodoService} from "../shared/todoService"
#Component({
moduleId: module.id,
selector: "todo-form",
templateUrl: "todo-form.component.html",
styleUrls: ["todo-form.component.css"],
})
export class TodoForm {
...
constructor(private todoService:TodoService) {
console.log(this.todoService);
this.todoService.order = 2;
console.log( this.todoService);
}
}
todo-list.component.ts:
import {Component, Input, OnInit} from "#angular/core"
import { ITodo } from "../shared/todo.model"
import { TodoService } from "../shared/todoService"
#Component({
moduleId: module.id,
selector: "todo-list",
templateUrl: "todo-list.component.html",
styleUrls: ["todo-list.component.css"],
})
export class TodoListComponent implements OnInit {
todos:ITodo[];
...
constructor(private todoService:TodoService) {
...
console.log(this.todoService);
this.todoService.order=1;
console.log(this.todoService);
}
...
}
app is the parent of the list and form components
Whaen I start application I see in console:
but if expand all I see:
Which result actual and why in second view I see 1 and in another 2.
The console.log '+' button can only show you the current state of the object, not the object at the snapshot in time of when it was called.
See console.log() async or sync? for a more in depth explanation.
So order: 1, is the final state of the object.
never use providers( providers: [TodoService] ) in component
as
import { Component } from "#angular/core"
import { Todo } from './components/shared/todo.model'
import { todos } from "./components/shared/todo.data"
import {TodoService} from "./components/shared/todoService"
import {TodoService} from "./components/shared/todoService";
#Component({
moduleId: module.id,
selector: "app",
templateUrl: "app.component.html",
styleUrls: ['app.component.css']
})
export class AppComponent {
title:string = "Angular 2Do";
}
it makes new instance when component initialise so put providers in module only ie. NgModule
I have an AlertComponent that I would like to use as a directive in my AppComponent and expose it so that it's available (as a sort of singleton) to all the routes/children components from AppComponent. But I can't seem to find a way to get the instance of the AlertComponent object used as a directive in order to call it's methods and see the changes made on the directive (i.e. add/remove alerts to/from the page).
Here is AlertComponent:
import { Component } from 'angular2/core';
import { Alert } from './model';
#Component({
selector: 'alerts',
templateUrl: './alert/index.html'
})
export class AlertComponent {
alerts: Array<Alert>;
constructor() {}
add(alert: Alert) {
this.alerts.push(alert);
}
remove(index: number) {
this.alerts.splice(index, 1);
}
clear() {
this.alerts = [];
}
}
export { Alert };
And AppComponent:
import { Component, OnInit, provide } from 'angular2/core';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router';
import { HTTP_PROVIDERS, RequestOptions } from 'angular2/http';
import { CookieService } from 'angular2-cookie/core';
import { UserComponent } from '../user/component';
import { AlertComponent, Alert } from '../alert/component';
import { ExtendedRequestOptions } from '../extended/RequestOptions';
import { UtilObservable } from '../util/observable';
#Component({
selector: 'app',
template: `
<alerts></alerts>
<router-outlet></router-outlet>
`,
//styleUrls: [ 'app/style.css' ],
directives: [
ROUTER_DIRECTIVES,
AlertComponent
],
providers: [
ROUTER_PROVIDERS,
HTTP_PROVIDERS,
provide(RequestOptions, { useClass: ExtendedRequestOptions }),
CookieService,
UtilObservable,
AlertComponent
]
})
#RouteConfig([{
path: '/user/:action',
name: 'User',
component: UserComponent,
useAsDefault: true
}
])
export class AppComponent implements OnInit {
constructor(public _alert: AlertComponent) {}
ngOnInit() {
this._alert.add(new Alert('success', 'Success!'));
}
}
I'd like to have the same instance of AlertComponent available to all descendant routes/children of AppComponent (e.g. UserComponent), so as to add alerts to the same directive.
Is this possible? Or is there another, more proper way to do this?
[Update]
The chosen solution answers the title question, but I also wanted to have a simple solution to share alerts among my components. Here's how to do that:
AlertComponent:
import { Component } from 'angular2/core';
import { Alert } from './model';
export class Alerts extends Array<Alert> {}
#Component({
selector: 'alerts',
templateUrl: './alert/index.html'
})
export class AlertComponent {
constructor(public alerts: Alerts) {}
add(alert: Alert) {
this.alerts.push(alert);
}
remove(index: number) {
this.alerts.splice(index, 1);
}
clear() {
this.alerts.length = 0;
}
}
export { Alert };
AppComponent:
import { Component, provide } from 'angular2/core';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router';
import { HTTP_PROVIDERS, RequestOptions } from 'angular2/http';
import { AlertComponent, Alerts } from '../alert/component'
import { UserComponent } from '../user/component';
import { ExtendedRequestOptions } from '../helpers/extensions';
#Component({
selector: 'app',
template: `<router-outlet></router-outlet>`,
directives: [
ROUTER_DIRECTIVES
],
viewProviders: [
provide(Alerts, { useValue: [] })
],
providers: [
ROUTER_PROVIDERS,
HTTP_PROVIDERS,
provide(RequestOptions, { useClass: ExtendedRequestOptions })
]
})
#RouteConfig([{
path: '/user/:action',
name: 'User',
component: UserComponent,
useAsDefault: true
}
])
export class AppComponent {}
Basically, I'm providing a singleton array of alerts that's used by every AlertComponent.
You can move the provide() to providers (instead of viewProviders) if you want to use it outside of directives, but if not, keep it simple and restrict it this way.
Hope this helps someone :)
You need to use ViewChild decorator to reference it:
#Component({
})
export class AppComponent implements OnInit {
#ViewChild(AlertComponent)
_alert: AlertComponent;
ngAfterViewInit() {
// Use _alert
this._alert.add(new Alert('success', 'Success!'));
}
}
#ViewChild is set before the ngAfterViewInit hook method is called.
expose it so that it's available (as a sort of singleton) to all the
routes/children components from AppComponent.
Or is there another, more proper way to do this?
Create and bootstrap a service for AlertComponent, like this
AlertService
import {Injectable} from '#angular/core';
import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/share';
#Injectable()
export class AlertService {
private _alerts: Array<Alert> = [];
public alertsChange: Subject<Array<Alert>> = new Subject();
public get alerts(): Array<Alert> {
return this._alerts;
}
add(alert: Alert) {
this._alerts.push(alert);
this.alertsChange.next(this._alerts);
}
remove(index: number) {
this._alerts.splice(index, 1);
this.alertsChange.next(this._alerts);
}
clear() {
this._alerts = [];
this.alertsChange.next(this._alerts);
}
}
Bootstrap AlertService
import {bootstrap} from '#angular/platform-browser-dynamic';
import {YourApp} from 'path/to/YourApp-Component';
import { AlertService} from 'path/to/alert-service';
bootstrap(YourApp, [AlertService]);
AlertComponent
import { Component } from 'angular2/core';
import { Alert } from './model';
import { AlertService} from 'path/to/alert-service';
#Component({
selector: 'alerts',
templateUrl: './alert/index.html'
})
export class AlertComponent {
alerts: Array<Alert>;
constructor(alertService: AlertService) {
alertService.alertsChange.subscribe((moreAlerts: Array<Alert>) => {
this.alerts = moreAlerts;
})
}
}
All the routes/children components
(sample):
import { Component} from '#angular/core';
import { AlertService} from 'path/to/alert-service';
#Component({
template: `.....`
})
export class SampleComponent {
constructor(public alerts: AlertService){}
ngOnInit(){
this.alerts.add(new Alert('success', 'Success!'));
}
ngOnDestroy(){
this.alerts.clear();
}
}
To see other alike examples see this question