Angular2 - 'watch' provider property in multiple components

I come to the NG1 environment and I am currently building an NG2 application with all the features available. Before asking, I studied google and stackoverflow questions, but no luck, as angular 2 moved so fast with api architecture and most of the answers are outdated.

My case: I have an Auth provider (service) with user properties, I would like to observe the user and respond to several components (navbar, sidebar, etc.).

What I tried:

@Injectable(); export class Auth { private user; authorized: EventEmitter<boolean>; constructor(public router:Router){ this.authorized = new EventEmitter<boolean>(); } login(user, token):void{ localStorage.setItem('jwt', token); this.user = _.assign(user); this.authorized.emit(<boolean>true); this.router.parent.navigateByUrl('/'); } } /***************/ @Component({...}) export class NavComponent { public isAuthroized: boolean = false; constructor(Auth:Auth){ Auth.authorized .subscribe((data) => this.onUserChanged(data)); } onUserChanged(user){ alert('USER:' + user.email); this.isAuthroized = true; } } /****************/ bootstrap(AppComponent, [ ROUTER_PROVIDERS, ELEMENT_PROBE_PROVIDERS, HTTP_PROVIDERS, MapLoader, Auth ]) 

But no luck. Should I use an Observable EventEmitter or maybe there is another correct approach to handle this case? In NG1, it would be as simple as setting $ watch on a service property. Thank you

EDIT: I added a new method for the Auth service:

 ... userUpdated: EventEmitter<boolean>; constructor(public router:Router){ this.userUpdated = new EventEmitter<any>(); } ... logout(returnUrl?: string): void{ delete this.user; localStorage.removeItem('jwt'); this.userUpdated.emit(undefined); if(!_.isEmpty(returnUrl)){ this.router.parent.navigateByUrl(returnUrl); } } 

And now an event is fired, why does it work for logging out, not logging in?

EDIT 2:

 export class LoginPageComponent { error: string; constructor(public http: Http, public router: Router, public Auth:Auth){ } login(event, email, password){ ... this.http.post('/api/login', loginModel, {headers: headers}) .map((res) => res.json()) .subscribe((res: any) => { this.Auth.login(res.user, res.ADM_TOKEN); }, (error) => this.error = error._body); } } 

RESOLVED

Stupid mistake. I left NavComponent in an array of providers [Auth] .. so it was a different object than global Auth .. sorry guys! Hope this problem helps someone new in Angular2. Thanks for your efforts.

+5
source share
2 answers

I assume that you add Auth as a provider for each component. This creates a new instance of the class for each component. Add it only to bootstrap(AppComponent, providers: [...]) or only to AppComponent .

+1
source

You may notice that Angular does not have a view function, as it is now zone controlled.

To notify other components, you can add another EventEmitter to your Auth service for the userUpdated event. Components that want to be notified can register with this emitter.

 @Injectable(); export class Auth { private user; authorized: EventEmitter<boolean>; userUpdated: EventEmitter<boolean>; constructor(public router:Router){ this.authorized = new EventEmitter<boolean>(); this.userUpdated = new EventEmitter<boolean>(); } login(user, token):void{ localStorage.setItem('jwt', token); this.user = _.assign(user); this.authorized.emit(<boolean>true); this.userUpdated.emit(this.user); this.router.parent.navigateByUrl('/'); } } 

Components can register for this event:

 @Component({...}) export class NavComponent { (...) constructor(Auth:Auth){ Auth.userUpdated .subscribe((data) => this.onUserChanged(data)); } } 

You can also tell the user when emitting an authorized event:

  login(user, token):void{ localStorage.setItem('jwt', token); this.user = _.assign(user); this.authorized.emit(this.user); this.router.parent.navigateByUrl('/'); } } 

Hope this helps you, Thierry

+1
source

Source: https://habr.com/ru/post/1239771/


All Articles