2016-04-12 12 views
2

Ich habe Beispiele gesehen, bei denen Code in eine setTimeout-Funktion eingeschlossen wird, um zu vermeiden, dass Vorlagen/Komponenten ohne die Daten erzeugt werden, auf denen sie warten. Ich möchte mit dem jQuery Bootstrap-Multiselect eine Liste von Organisationen anzeigen.Angular 2: setTimeout für alles?

ngOnInit(){ 
    this._panelService.getOrgs() 
    .subscribe(
     orgs => this.orgs = orgs, 
     error => alert('There was an error connecting to the API'), 
    () => setTimeout(() => jQuery('#organizations').multiselect(), 0)); 
} 

Ich habe es auch an anderen Orten verwendet. In diesem Fall bin ich rufe die API nach einem löschen, um eine Änderung in einem * ngFor auslösen:

deleteBoard(panelId: number, boardId: number) { 
    this._boardService.deleteBoard(panelId, boardId) 
    .subscribe(
     boards => this.panel.boards = boards, 
     error => alert('There was an error contacting the API.'), 
    () => setTimeout(this._boardService.getAvailableRanks(panelId) 
     .subscribe(ranks => this.updatedRanks = ranks), 0)); 
} 

* ngFor die Änderung nicht erkennen, es sei denn, ich setTimeout verwenden. Was habe ich verpasst?

Ich bin mit Beta 14

Antwort

0

*ngFor muss in der Lage sein, seine Arbeit zu tun. Dazu müssen Sie den Aufruf von jQuery in die Ereigniswarteschlange unter Verwendung von setTimeout in die Warteschlange stellen. Wenn Sie es synchron ausführen, erhält *ngFor kein Zeitfenster, um die Updates zu verarbeiten.

0

Wenn Sie die Lösch Anruf warten soll vollständig sein und dann Sie Reihen neu zu laden, würde ich den flatMap Betreiber nutzen:

deleteBoard(panelId: number, boardId: number) { 
    this._boardService.deleteBoard(panelId, boardId) 
    .map(res => res.json()) 
    .flatMap((board) => { 
     this.panel.boards = boards, 
     return this._boardService.getAvailableRanks(panelId) 
     .map(res => res.json()); 
    }) 
    .subscribe(ranks => this.updatedRanks = ranks)); 
} 
0

Es klingt wie Sie zone.js. müssen schließen Es wird helfen, Angular realize Veränderungen aufgetreten sind (man denke an sie fast wie die Art und Weise verdauen in Angular1 war)

"zone.js": "0.6.10" // add it in dependencies 
5

Winkeländerungserkennung nach jedem asynchronen Ereignisses automatisch ausgeführt wird, wenn das asynchrone Ereignis wurde von Zone Affen gepatcht .js. Während der Änderungserkennung werden NgFor-Bindungen auf Änderungen überprüft. Wenn Änderungen gefunden werden, wird das DOM aktualisiert.

Ich nehme an, deleteBoard() verwendet eine Art asynchrones Ereignis, aber dieses Ereignis ist wahrscheinlich nicht von Zone.js monkey-patchen. setTimeout() ist Affe-gepatcht, also wird das Aufrufen der Änderungserkennung ausgelöst.

Anstelle von setTimeout() können Sie auch ChangeDetectorRef injizieren und dessen detectChanges()-Methode aufrufen, die Änderungen an dieser Komponente und ihren Nachkommen erkennt. Dies ist eine weitere Möglichkeit, die Änderungserkennung manuell auszulösen.

Es gibt jedoch einen Unterschied zwischen den beiden Ansätzen. Mit setTimeout() kann der Browser die Ansicht rendern, bevor die Callback-Funktion aufgerufen wird. Und manchmal brauchst du das. Mit detectChanges() wird die Änderungserkennung ausgeführt, bevor der Browser die Ansicht rendern kann. Verwenden Sie detectChanges(), wenn Sie können, da es effizienter ist (ein Änderungszyklus wird weniger ausgeführt).

+0

Danke für den Tipp. –