2016-07-19 14 views
4

Ich erfahre etwas unerwartetes Verhalten in Angular2, wenn ich einen ngIf Container um eine Liste wickeln, die mit ngFor erstellt wurde. Es scheint, als ob die Ansicht Objekte in dem beobachtbaren Array nicht beim ersten Einfügen wiedergibt, nachdem der Container sichtbar geworden ist.ngIf Container bricht async ngFor

Bitte beachten Sie die plunker demo, die dieses unerwartete Verhalten zeigt. Ich erwarte, dass das erste Beispiel würde zeigen Banane gleichzeitig Loaded erscheint.

Mache ich etwas Dummes oder ist das ein Renderfehler?


Plunker demo

app.service.ts

export class AppService { 
    private _things = new Subject<Array<any>>(); 
    public things = this._things.asObservable(); 

    constructor() { 
    var that = this; 

    // simulate ajax request 
    setTimeout(function() { 
     that._things.next([ 
      {'id': 1, 'text': 'banana'} 
     ]); 
    }, 3000); 

    setTimeout(function() { 
     that._things.next([ 
     {'id': 1, 'text': 'banana'}, 
     {'id': 2, 'text': 'orange'} 
     ]); 
    }, 6000); 

    setTimeout(function() { 
     that._things.next([ 
     {'id': 1, 'text': 'banana'}, 
     {'id': 2, 'text': 'orange'}, 
     {'id': 3, 'text': 'apple'} 
     ]); 
    }, 9000); 
    } 
} 

app.ts

@Component({ 
    selector: 'my-app', 
    template: ` 
    <h4>Does have *ngIf</h4> 
    <div *ngIf="hasThings"> 
     Loaded 
     <ul> 
     <li *ngFor="let thing of things | async"> 
      {{thing.id}}: {{thing.text}} 
     </li> 
     </ul> 
    </div> 

    <h4>Doesn't have *ngIf</h4> 
    <div> 
     Loaded 
     <ul> 
     <li *ngFor="let thing of things | async"> 
      {{thing.id}}: {{thing.text}} 
     </li> 
     </ul> 
    </div> 
    `, 
    directives: [NgClass, NgStyle, CORE_DIRECTIVES, FORM_DIRECTIVES] 
}) 
export class App implements OnInit { 
    public hasThings = false; 

    private _things = new Subject<Array<any>>(); 
    public things = this._things.asObservable(); 

    constructor(private _appService: AppService) { 
    } 

    ngOnInit() { 
    this._appService.things 
     .subscribe(things => { 
     this.hasThings = things.length > 0; 
     this._things.next(things); 
     }); 
    } 
} 
+0

Ihr zupfen scheint für mich zu arbeiten ... –

Antwort

5

Der Grund ist, dass Sie Subject in Ihrer Komponente und async Rohr in Ihrer Vorlage verwenden. Wenn Sie das Objekt Subject in Ihrer Komponente zu BehaviorSubject ändern, erhalten Sie das erwartete Ergebnis.

private _things = new BehaviorSubject<Array<any>>(); 

Einer der wichtigsten Unterschiede zwischen Subject und BehaviorSubject ist BehaviorSubject kehrt man der letzte Wert es für richtig hält, wenn Sie ihn abonnieren, wenn Subject nicht. Wenn in Ihrem Code die erste ngIf Bedingung erfüllt ist, wird das DOM initiiert und die erste Liste ruft subscribe auf. Zu diesem Zeitpunkt wird Subject nichts ausgeben und Sie müssen bis zum nächsten Ereignis warten, um die Liste zu aktualisieren.

Arbeiten plnkr: https://plnkr.co/edit/Obso0Odl3PoPw699AQ5W?p=preview

+1

Haben Sie versucht es? Weil es nicht zu funktionieren scheint. – sirrocco

+2

Yup, hier ist mein PLNKR (Gegabelt von seinem, nur bearbeitet Import Zeile und Deklaration): https://plnrkr.co/edit/Obso0Odl3PoPw699AQ5W?p=preview –

+0

Ah super, danke! Anfangs dachte ich, dass es auch nicht funktionierte, da ich das "BehaviorSubject" für den Dienst anstelle der Komponente verwendete. Ich nehme an, es sollte wahrscheinlich für beide verwendet werden. Kann ich vorschlagen, dass Sie Ihre Antwort aktualisieren, um Unklarheiten zu beseitigen? – ajbeaven

Verwandte Themen