Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 585
Jacek Pudysz Avatar asked Oct 30 '22 12:10

Jacek Pudysz


1 Answers

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.

like image 129
Günter Zöchbauer Avatar answered Nov 11 '22 11:11

Günter Zöchbauer