Reputation: 2587
In an effort to pass a variable into app.component.ts from another component I created a service (see Global.service.ts below.)
This works well when my nav.component.ts calls the service. However, it doesn't work in app.component.ts. I don't understand why, as the code is the same (see app.component.ts below.)
Nav.component.ts is in a module (global.module.ts). global.module.ts has been added to the imports [] in app.module.ts.
Global.service.ts
@Injectable()
export class GlobalService {
private handleError: HandleError;
isOpen = false;
private _change: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor(
private http: HttpClient,
httpErrorHandler: HttpErrorHandler
) {
this.handleError = httpErrorHandler.createHandleError('GlobalService');
}
get change(): Observable<boolean> {
return this._change.asObservable();
}
toggle() {
this.isOpen = !this.isOpen;
this._change.next(this.isOpen);
}
}
app.component.ts
import { Component, OnInit } from '@angular/core';
import { GlobalService } from './globals/global.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
isOpen = true;
constructor(
private _globalService: GlobalService,
) {
}
ngOnInit(): void {
console.log("foo bar");
this._globalService.change.subscribe(isOpen => {
this.isOpen = isOpen;
console.log(this.isOpen);
});
}
}
nav.component.ts
ngOnInit(): void {
//
this.getNav();
this._globalService.change.subscribe(isOpen => {
this.isOpen = isOpen;
this.NavToggle(this.isOpen);
});
}
//Toggle
hideShowSidebar() {
this._globalService.toggle();
}
Upvotes: 1
Views: 2914
Reputation: 2872
The @Output
(and @Input
) decorators are typically used for attributes/properties of components/elements to detect events (and assign values), I would say that it would not be the best way for a Service to emit an update to a Component. For that you could use a simple BehaviorSubject and just a little change to your service.
@Injectable()
export class GlobalService {
private handleError: HandleError;
isOpen = false;
private _change: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor(
private http: HttpClient,
httpErrorHandler: HttpErrorHandler
) {
this.handleError = httpErrorHandler.createHandleError('GlobalService');
}
get change(): Observable<boolean> {
return this._change.asObseravble();
}
toggle() {
this.isOpen = !this.isOpen;
this._change.next(this.isOpen);
}
}
Since the _change
BehaviorSubject provides as a source of truth for components/classes outside of itself, we do not want to expose it (as it can be easily changed). That is why we provide it through the get
ter as an Observable. This should work however if you have the service imported into the providers of multiple modules, you may have multiple instances of the service (and they wouldn't all have the same data). If that is the case it would be best to only have your service declared in only your AppModule
.
Upvotes: 2