2017-08-17 36 views
5

Dla mojej aplikacji, ItemDetailComponent jest tam, gdzie będą wyświetlane informacje o produkcie. Mam usługę, która pobiera wszystkie przedmioty za pomocą obietnicy. Używam ActivatedRoute, aby pobrać identyfikator przedmiotu ze ścieżki URL, następnie uruchomić usługę, pobrać wszystkie elementy, a następnie znaleźć przedmiot z identyfikatorem, który został pobrany powyżej, i przypisać go do zmiennej selectedItem.Jak utworzyć szablon HTML Angular 2 po rozwiązaniu obietnicy w komponencie?

Oto item-detail.component.ts:

export class ItemDetailComponent implements OnInit { 
    private title = 'Item Details' 
    private selectedItem: object 

    constructor(
    private route: ActivatedRoute, 
    private itemService: ItemService 
) {} 

    ngOnInit() { 
    const selectedItemId = this.route.snapshot.params.itemId 

    return this.itemService.getAllItems() 
     .then((items) => { 
     return _.find(items, item => item.itemId === selectedItemId) 
     }) 
     .then((selectedItem) => { 
     this.selectedItem = selectedItem 
     console.log('Inside promise', this.selectedItem) 
     }) 
    console.log('Outside promise', this.selectedItem) 
    } 
} 

A oto item-detail.component.html szablon więc może wyświetlać moją pozycję, to tylko przykład:

<div> 
    <h1>{{title}}</h1> 

    <div *ngIf="selectedItem"> 
    <div><label>Item ID: </label>{{selectedItem.itemId}}</div> 
    </div> 
</div> 

Aplikacja zwraca nic, ale tytuł niestety. Następnie dodałem dwie komendy console.log() i okazało się, że zarówno poza obietnicą, jak i szablonem html są renderowane przed spełnieniem obietnicy, a w tej chwili nie jest dostępna żadna wersja console.log(). W jaki sposób mogę wymusić na aplikacji ich wykonanie dopiero po rozwiązaniu obietnicy, aby mieć gotowy numer selectedItem?

EDIT: Dodałem nową linię w szablonie html badać dalej:

<div> 
    <h1>{{title}}</h1> 
    <div><label>Item ID 1: </label>{{selectedItem.itemId}}</div> 
    <div *ngIf="selectedItem"> 
    <div><label>Item ID 2: </label>{{selectedItem.itemId}}</div> 
    </div> 
</div> 

Aplikacja wyświetla "Item ID 1:" etykieta ale bez rzeczywistej id tam. Konsola pokazuje mi komunikat o błędzie "Nie można odczytać właściwości 'itemId' of undefined", ponownie potwierdzając, że cały szablon jest renderowany przed rozstrzygnięciem obietnicy i nie jest ponownie renderowany po załadowaniu danych. Bardzo dziwne.

+1

* "Jak mogę zmusić aplikację do jej wykonania dopiero po rozwiązaniu obietnicy, aby ve wybrany element na miejscu? "*. Nie musisz. Szablon zostanie automatycznie zrerenderowany. Prawdziwym pytaniem jest czy otrzymasz log w "Inside Promise" i 'selectedItem' zostanie poprawnie rozwiązany? – dfsq

+0

Tak, wewnętrzny dziennik obietnic pokazuje mi dokładnie ten przedmiot, który chcę wyświetlić szczegóły. – Duc

+1

to tytuł własności związany ok? możesz opublikować plunkr pls – Tsar

Odpowiedz

0

dodać zmienną logiczną do klasy jak

prywatnej dataAvailable: Boolean = false;

aw subskrypcji obietnicy zrobić to prawda, gdy dane są dostępne

then((selectedItem) => { 
     this.selectedItem = selectedItem; 
this.dataAvailable=true; 
     console.log('Inside promise', this.selectedItem) 
     }) 

i w szablonie czynią, gdy dane są dostępne

<div> 
    <h1>{{title}}</h1> 

    <div *ngIf="dataAvailable"> 
    <div><label>Item ID: </label>{{selectedItem.itemId}}</div> 
    </div> 
</div> 

Należy rade

+0

Po prostu próbowałem i to nie pomogło. Myślałem również, że to nie zadziała, ponieważ zarówno 'selectedItem' i' dataAvailable' są przypisywane nowe wartości w tej samej obietnicy w tym samym czasie, więc nie ma to żadnej różnicy. – Duc

+0

, jak wskazał dfsq, szablon powinien zostać ponownie wydany po udostępnieniu danych.! .. Czy możesz stworzyć pluna dla tego samego? –

+0

Dość dużo pracy, aby zrobić plunker do tego, ponieważ usługa pozycji pobiera informacje z kontenera dokera, który łączy się ze zdalnym serwerem w dev. – Duc

0

Aktualizacja

ngOnInit() wydaje się być tylko hak obsługi zdarzeń - powrocie nic nie wpłynie nic się wydaje. Dlatego moja stara odpowiedź nie zadziała.

Istnieją inne sposoby obejścia, takie jak używanie * ngIf lub umieszczanie go w trasach itp., Ale chciałbym, aby było coś takiego jak haczyk resolvePromise(): Promise, który ustawiłby warunek rozdzielczości przed renderowaniem.

To jest zamiast programistów umieszczających płytę główną w każdym komponencie.

Old odpowiedź

Najprawdopodobniej to dlatego, że brakuje instrukcji return w drugim then.

then((selectedItem) => { this.selectedItem = selectedItem console.log(): return selectedItem;// }

+0

Po prostu wypróbowany, szkoda, że ​​to nie jest to :( – Duc

0

Czy to możliwe, że ChangeDetection jest ustawiony na OnPush gdzieś drzewie komponentu? W takim przypadku szablon nie jest automatycznie ponownie wysyłany, ponieważ nic nie uruchamia dla tego komponentu wartości ChangeDetection.

Wypatruj komponent z ustawieniem changeDetection: ChangeDetectionStrategy.OnPush

@Component({ 
    selector: 'example', 
    template: `...`, 
    styles: [`...`], 
    changeDetection: ChangeDetectionStrategy.OnPush 
}) 

Również masz już poprawny rozwiązanie za pomocą Resolver można sprawdzić, czy to pomaga:

export class ItemDetailComponent implements OnInit { 
    private title = 'Item Details' 
    private selectedItem: object 

    constructor(
     private route: ActivatedRoute, 
     private itemService: ItemService, 
     // the reference to the components changeDetector is needed. 
     private changeDetectorRef: ChangeDetectorRef 
    ) {} 

    ngOnInit() { 
     const selectedItemId = this.route.snapshot.params.itemId 

     return this.itemService.getAllItems() 
      .then((items) => { 
       return _.find(items, item => item.itemId === selectedItemId) 
     }) 
     .then((selectedItem) => { 
      this.selectedItem = selectedItem 
      // this triggers the changedetection and the template should be rerendered; 
      this.changeDetectorRef.detectChanges(); 
      console.log('Inside promise', this.selectedItem) 
     }); 
     console.log('Outside promise', this.selectedItem) 
    } 
} 

Oto wielki artykuł about Angulars ChangeDetection: https://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html