Search code examples
angularobservableeventemitter

Angular2 - 'watch' provider property in multiple components


I'm coming form NG1 environment and currently I'm creating NG2 app with all available features. Before asking I was exploring google and stackoverflow questions but with no luck since angular 2 moved so fast with api architecture and most answers are out of date.

My case: I have Auth provider (service) with property user, I would like to observe user and react in multiple 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 with no luck. Should I use Observable EventEmitter or maybe there is other correct approach to handle this case? In NG1 it would be as simple as set $watch on service's property. Thanks!

EDIT: I added new method to 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 event is called, why is this working for logout and not for login?

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

Silly mistake.. i left in NavComponent in providers array [Auth].. so it was different object than global Auth.. sorry guys! Hope this issue will help somebody new in Angular2. Thanks for your effort.


Solution

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