2016-07-19 2 views
4

Я испытываю некоторое неожиданное поведение в Angular2, когда я обертываю контейнер вокруг списка, созданного с помощью ngFor. Похоже, что представление не отображает элементы в наблюдаемом массиве при первом вставке после того, как контейнер ngIf становится видимым.ngIf контейнер перерывы async ngFor

См. 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

Ваш звенеть, кажется, работает для меня ... –

ответ

5

Причина в том, что вы используете Subject в своем компоненте и async в вашем шаблоне. Если вы измените объект Subject в своем Компоненте на BehaviorSubject, вы получите ожидаемый результат.

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

Одним из основных отличий между Subject и BehaviorSubject это BehaviorSubject возвращает вас последнее значение он сохраняет право при подписке на него, когда Subject нет. В вашем коде, когда первое условие ngIf выполнено, DOM инициируется и первый список вызывает subscribe. В то время Subject ничего не выдаст, и вам нужно дождаться следующего события, чтобы обновить список.

Работа plnkr: https://plnkr.co/edit/Obso0Odl3PoPw699AQ5W?p=preview

+1

Пробовали ли вы это? Потому что это не работает. – sirrocco

+2

Yup, вот мой plnkr (Forked из его, только отредактированная строка импорта и строка декларации): https://plnkr.co/edit/Obso0Odl3PoPw699AQ5W?p=preview –

+0

Ах, отлично, спасибо! Первоначально я думал, что это не работает, поскольку я использовал «BehaviorSubject» для службы вместо компонента. Полагаю, что он, вероятно, должен быть использован для обоих. Могу ли я предложить вам обновить свой ответ, чтобы устранить двусмысленность? – ajbeaven

Смежные вопросы