2016-07-19 5 views
4

ngForを使用して作成されたリストの周りにngIfコンテナをラップすると、Angular2で予期しない動作が発生します。 ngIfコンテナが表示された後で初めてビューが挿入されたときに、オブザーバブル配列内のアイテムが表示されないように見えます。ngIfコンテナが非同期に破棄される

この予期しない動作を示すplunker demoを参照してください。私は、最初の例がバナナを同時に表示することを期待していますがロードされましたが表示されます。

私は何か愚かなことをしていますか、これはレンダリングのバグですか?


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

あなたplunkが私のために働くようだ... –

答えて

5

理由は、コンポーネントにSubject、テンプレートにasyncパイプを使用しているためです。コンポーネント内のSubjectオブジェクトをBehaviorSubjectに変更すると、予期した結果が得られます。 SubjectがないときSubjectBehaviorSubjectの主な違いの

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

一つは、BehaviorSubject戻りますあなたがそれに加入するとき、それは右保つ最後の値です。あなたのコードでは、最初にngIfの条件が満たされると、DOMが開始され、最初のリストはsubscribeを呼び出します。その時、Subjectは何も放出しないので、あなたはリストを更新するために次のイベントまで待たなければなりません。 plnkrの作業

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

+1

あなたはそれを試してみましたか?それは動作しないように見えるので。 – sirrocco

+2

うん、ここに私のplnkr(彼の唯一の編集インポートラインと宣言ラインからフォーク):https://plnkr.co/edit/Obso0Odl3PoPw699AQ5W?p=preview –

+0

ああ、ありがとう!当初はコンポーネントの代わりにサービスのために 'BehaviorSubject'を使用していたので、どちらも動作していないと思っていました。私はそれがおそらく両方のために使用されるべきだと思います。あいまいさを解消するために答えを更新することを提案できますか? – ajbeaven

関連する問題