2016-06-23 9 views
2

В предыдущем вопросе here, я пытаюсь показать дату только тогда, когда она изменилась между двумя сообщениями.Angular2: * ngFor, AsyncPipe и index

Разница заключается в том, что я сейчас подключен к базе данных в реальном времени (Firebase), поэтому я присоединяюсь к источнику данных и передать его через асинхронном трубу перед выходом через индекс и * ngIf:

<div *ngFor='let message of (chat | async) ; let i = index'> 
    <button *ngIf="i == 0 || (message.timestamp | date: 'ddMMMMyyyy') != ((chat | async)[i-1].timestamp | date: 'ddMMMMyyyy')"> 
     {{ message.timestamp | date:'ddMMM' }} 
    </button> 
    ... 
    <!--More html elements below (omitted)--> 
    ... 
</div> 

Этот хорошо работает, когда я сначала загрузить вид, однако, если я нажимаю новую запись в chat, я получаю следующее сообщение об ошибке:

TypeError: Cannot read property '0' of null

Может быть, я не слишком уверен, как Асинхронная труба работает, но когда я пытаться возвращается {{ (chat | async).length }}, он работает по назначению. Любые предложения по обходной/надлежащей практике?

+0

ли вы проверить, если '' || Короткое замыкание при использовании в шаблоне? Может быть, ошибка. –

+0

@ GünterZöchbauer Короткое замыкание предназначено, поскольку перед сообщением с индексом 0 нет ничего, поэтому он должен возвращать true. В индексе 1 '[i-1]' оценивается как 0, и именно там генерируется исключение. – shinglesmingles

+0

Я знаю, что это предназначено, но я подозрительно, действительно ли это происходит. –

ответ

2

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

Я подписываюсь на источник данных в своем классе и манипулирую массивом с циклом for перед его отображением.

The (шаблон) код в мой вопрос теперь стал:

<div *ngFor='let message of messages; let i = index'> 
    <button *ngIf="message.isNewDay"> 
     {{ message.timestamp | date:'ddMMM' }} 
    </button> 
    ... 
    <!--More html elements below (omitted)--> 
    ... 
</div> 

И в контроллере:

private chatid: string //chat id passed from previous screen 
private chat: FirebaseListObservable<any>; 
private messages: any = []; 

constructor(private firebase: FirebaseService, 
      private _datepipe: DatePipe) { 
} 

ionViewLoaded() { 
    this.chat = this.firebase.database.list('/chat-messages/' + this.chatid); 
    this.chat.subscribe((data) => { 
     this.messages = data; 
     for (let i: number = 0; i < this.messages.length; i++) { 
      if (i === 0) 
        this.messages[i].isNewDay = true; 
      else { 
       let date1 = this._datepipe.transform(this.messages[i].timestamp, 'ddMMMMyyyy'); 
       let date2 = this._datepipe.transform(this.messages[i-1].timestamp, 'ddMMMMyyyy'); 
       if (date1 !== date2) 
        this.messages[i].isNewDay = true; 
       else 
        this.messages[i].isNewDay = false; 
      } 
     } 
    }); 
} 

Следует заметить, что я в настоящее время с помощью DatePipe в коде класса (а также в шаблоне), поэтому необходимо использовать providers: [DatePipe] вместе с pipes: [DatePipe].

3

В случае, если кто-то считает, что это, так как это первый результат с ключевыми словами, я был в состоянии получить индекс а * ngFor с асинхронной трубы, как это (предполагается, что messages является Наблюдаемые из итератора):

<div *ngFor="let message of (messages | async); let i = index;"> 
0

Я использую функцию для показа (или отсутствия) даты. Таким образом, чтобы показать дату (в данном примере) только тогда, когда она меняется:

<ion-list no-lines> 
<ion-item-sliding *ngFor="let trip of tripsExt$ | async; let i = index"> 
    <ion-item> 
    <ion-row (click)="change(trip)"> 
     <ion-col col-6> 
     {{showOnChange(trip.date)}} 
     </ion-col> 
     <ion-col col-6> 
     {{trip.end_address_name}} 
     </ion-col> 
    </ion-row> 
    </ion-item> 
    <ion-item-options side="left"> 
    <button ion-button color="primary" (click)="delete(trip)"> 
     Delete 
    </button> 
    </ion-item-options> 
</ion-item-sliding> 
</ion-list> 

С showOnChange:

showOnChange(currentDate) { 
    if (currentDate != this.previousDate) { 
     this.previousDate = currentDate 
     return currentDate 
    } 
    return '' 
    }