2017-09-29 3 views
0

Ich bin ein wenig perplex. Ich dachte, dass ich den Lebenszyklus von Winkelkomponenten im Grunde genommen verstehe, aber dann stieß ich auf einen interessanten Fall, bei dem der @Input einer Komponente undefiniert war. In diesem Fall habe ich zwei Instanzen meiner Anwendung. Die angegebene Komponente: LogoutWarning wird angezeigt, wenn eine Abmeldung aussteht und der Benutzer dann das Anmelde-Token aktualisieren und fortfahren kann. Das funktioniert gut.Angular LifecyleHooks und wann ist @ViewChild gültig?

Die Instanz wird angezeigt, wenn die erste Anwendung das Anmelde-Token erneuert und die Komponente LogoutWarning ausblendet. Alles ist gut in dieser ersten Anwendung.

Die zweite Anwendung zeigt sie auch die LogoutWarning Komponente, da es die Login-Token erkannt würden abgelaufen werden und zeigt einen LogoutWarning modal, es dann bemerkt, dass die Login-Token wurden erneuert worden und ruft LogoutWarning.cancel () um das Modal zu verstecken. In diesem Fall explodiert this.logoutWarningModal.hide(), da this.logoutWarningModal UNDEFINED ist, obwohl das lifecyle ngAfterViewInit() anzeigt, dass this.logoutWarningModal definiert ist.

Ich bin an diesem Punkt sehr überrascht. Wenn ich einfach überprüfe, dass this.logoutWarningModal nicht definiert ist und nicht this.logoutWarningModal.hide() aufruft, funktioniert alles wie erwartet. Aber warum ist das.logoutWarningModal hier nicht definiert ???

Der Code für die LoutWarning Komponente ist einfach:

@Component({ 
    selector: 'logoutWarning', 
    template: ` 
    <div bsModal #logoutWarning="bs-modal" [config]="{ show: true }" class="modal fade" tabindex="-1" role="dialog" 
    aria-labelledby="new application version avaliable" aria-hidden="true" (onHidden)="hidden()"> 
     <div class="modal-dialog modal-sm"> 
     <div class="modal-content"> 
      <div class="modal-header"> 
      <div class="app_header"> 
       <div class="app_icon"><img src="assets/images/tracker_hi_res_512.gif"></div> 
       <div class="app_name">Tracker</div> 
      </div> 
      </div> 
      <div class="modal-body center-message"> 
      <span class="bold">You will be logged out in </span> 
      <span><strong>{{minutes | async}}</strong> minutes!</span> 
      </div> 
      <div class="modal-footer"> 
      <button class="btn btn-primary" (click)="ok()">Stay Logged In</button> 
      </div> 
     </div> 
     </div> 
</div> 
` 
}) 
export class LogoutWarning implements OnInit { 
    @ViewChild('logoutWarning') public logoutWarningModal: ModalDirective; 
    @Input() minutes: string; 

    constructor(private userCondition: UserCondition, private broadcaster: BroadCaster, private versionS: Version, private auth: AuthService) { 
    } 

    public ok(): void { 
    this.auth.renewLogin(this.userCondition, this.userCondition.minutesDurationUntilLogout.getValue()); 
    this.logoutWarningModal.hide(); 
    } 

    public cancel() { 
    if (this.userCondition.bShowLogoutWarning) { 
     this.logoutWarningModal.hide(); 
    } 
    } 

    public hidden() { 
    // reset the state of the dialog so that it can be reshown. 
    this.userCondition.bShowLogoutWarning = false; 
    this.logoutWarningModal.show(); 
    } 


    public ngOnInit() { 
    console.log('ngOnInit()'); 
    console.log('this:', this, this.logoutWarningModal); 
    } 

} 

und die Komponente wird angezeigt, wenn userCondtion.bShowLogoutWarning wahr ist und in meine Hauptanwendung gezeigt. Der entsprechende Abschnitt der HTML ist:

<logoutWarning *ngIf="userCondition.bShowLogoutWarning" [minutes]="userCondition.minutesUntilLogout"></logoutWarning> 

Beide Anwendungen log:

ngOnInit() logoutWarning.component.ts?f8b4:55 
this: LogoutWarning {userCondition: UserCondition, broadcaster: BroadCaster, versionS: Version, auth: AuthService, logoutWarningModal: ModalDirective, …} 
ModalDirective {onShow: EventEmitter, onShown: EventEmitter, onHide: EventEmitter, onHidden: EventEmitter, isAnimated: true, …} 
    userCondition.service.ts?0111:164 

Dann, nachdem die erste Anwendung, die Login-Token erneuert, die zweite Anwendung zeigt:

this: LogoutWarning {userCondition: UserCondition, broadcaster: BroadCaster, versionS: Version, auth: AuthService} undefined 

wo diese. logoutWarningModal ist NICHT DEFINIERT!

Vielen Dank für Ihre Einsicht!

Antwort

0

@ViewChild würde undefined zurückkehren, bis es initialisiert ist, und es ist der Fall in OnInit(). Überprüfen Sie es stattdessen in AfterViewInit():

+0

Das wirklich seltsame Problem ist, dass die Komponente bereits initialisiert und OnInit aufgerufen wurde. Aber der Aufruf in meinem app.module scheint auch die ursprüngliche LogoutWarning-Komponente von dem Provider aufzurufen, der beim Booten der App angegeben wurde. Gibt es eine Möglichkeit sicherzustellen, dass nur eine Instanz erstellt und geteilt wird k – JoelParke

Verwandte Themen