2016-01-04 5 views
5

Ich komme Form NG1-Umgebung und derzeit erstelle ich NG2 App mit allen verfügbaren Funktionen. Bevor ich mich erkundigte, erkunde ich google und stackoverflow-Fragen, aber ohne Glück, da sich angle 2 so schnell mit der API-Architektur bewegt hat und die meisten Antworten veraltet sind.Angular2 - 'Watch' Provider-Eigenschaft in mehreren Komponenten

Mein Fall: Ich habe Auth Anbieter (Service) mit der Eigenschaft Benutzer, würde Ich mag Benutzer beobachten und reagieren in mehreren Komponenten (navbar, Sidebar etc.)

Was ich versucht:

@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 
]) 

Aber ohne Glück. Sollte ich Observable EventEmitter verwenden oder gibt es vielleicht einen anderen richtigen Ansatz, um diesen Fall zu behandeln? In NG1 wäre es so einfach wie $ Watch auf Service-Eigenschaft setzen. Vielen Dank!

EDIT: Ich habe neue Methode Service von Auth:

... 
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); 
    } 

} 

Und jetzt Ereignis wird aufgerufen, warum ist das für Abmelde arbeiten und nicht für die Anmeldung?

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); 
    } 

} 

Dumme Fehler RESOLVED .. ich links in NavComponent in Anbieter array [Auth] .. so war es etwas anderes Objekt als global Auth .. sorry guys! Ich hoffe, dieses Problem wird jemandem in Angular2 helfen. Danke für Ihre Bemühungen.

+0

Also wird 'onUserChanged' nicht aufgerufen, nachdem' Auth.login() 'aufgerufen wurde? Ich habe eine einfache Version Ihres Beispiels (in Dart und ohne Routing und Localstorage) neu erstellt und es funktioniert gut. –

+0

Genau! Ich analysierte @thierry templier Antwort und ich habe den gleichen Code wie er und immer noch keine Warnung in onUserChanged. Beim Debuggen von NavComponent wird subscribe nur auf Konstruktor init ausgelöst. –

+0

Nicht sicher, ich verstehe Ihren letzten Kommentar. Könnte es sein, dass Ihre 'NavComponent' nur erstellt wird, nachdem das Ereignis ausgelöst wurde? –

Antwort

1

Ich nehme an, Sie fügen Auth als Anbieter für jede Komponente hinzu. Dies erstellt eine neue Instanz der Klasse für jede Komponente. Fügen Sie es nur in bootstrap(AppComponent, providers: [...]) oder nur auf dem AppComponent hinzu.

1

Sie können feststellen, dass es in Angular kein Watch-Feature gibt, da es jetzt von Zones verwaltet wird.

Um andere Komponenten zu benachrichtigen, könnten Sie innerhalb Ihres Auth Service für das userUpdated Ereignis einen weiteren EventEmitter hinzufügen. Die Komponenten, die benachrichtigt werden möchten, könnten sich bei diesem Sender registrieren.

@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('/'); 
    } 
} 

Komponenten zu dieser Veranstaltung registrieren können:

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

Sie können auch den Benutzer bereitstellen, wenn das authorized Ereignis emittierenden:

login(user, token):void{ 
    localStorage.setItem('jwt', token); 
    this.user = _.assign(user); 

    this.authorized.emit(this.user); 
    this.router.parent.navigateByUrl('/'); 
    } 
} 

Hoffe, es hilft Ihnen, Thierry

+0

Ok, aber das ist die Eigenschaft des Dienstes nicht der Komponente. Wie kann die Komponente wissen, dass sich das Feld des Service geändert hat? –

+1

Tatsächlich gibt es in Angular2 keine '$ watch'-Unterstützung, da es kein Konzept für den Umfang mehr gibt. Andere Komponenten müssten sich bei einem 'userChanged'-Ereignis anmelden. Ich habe meine Antwort auf diese Weise aktualisiert. –

+1

Sie können den Benutzer auch angeben, wenn Sie das 'autorisierte' Ereignis anstelle von' wahr' senden .... –