I'm new to Ionic 3 and firebase, and I'm trying to do a chat feature. My problem is when I update the array with new values, the whole list on view seems to flicker/blink. Is there a way to prevent this? Do I need to change my code?
Code(user-chat.ts)
getChats(){
//Add by index idea to avoid blinking?
this.chatObserver = this.db.list('chat', ref => ref.child(this.authKey).orderByChild('timestamp'))
.snapshotChanges().subscribe( snapshot => {
let reversedSnap = snapshot.slice().reverse();
let chatArray = [];
reversedSnap.forEach( element =>{
let data = element.payload.val();
data['id'] = element.key;
this.db.list('profile', ref=> ref.child(data['receiver'])).query.once('value', profileSnap => {
let profileData = profileSnap.val();
data['firstName'] = profileData.firstName;
data['lastName'] = profileData.lastName;
data['userImage'] = profileData.photos[0];
data['userKey'] = profileSnap.key;
})
this.db.list('messages', ref=> ref.child(this.authKey).child(data['id']).orderByChild('timestamp').limitToLast(1))
.query.once('value', messageSnap =>{
messageSnap.forEach( element =>{ //only returns one, foreach to include checking if got 1
let messageData = element.val();
Object.assign(data, messageData);
let message = ((data['sender'] === this.authKey)? "You: " : (data['firstName']+": "))+data['message'];
data['message'] = (message.length>25 ? message.substring(0, 25)+"..." : message);
data['messageDate'] = this.messageDateFormat(data['timestamp']);
});
chatArray.push(data);
});
});
this.chatList = chatArray;
});
}
View(user-chat.html)
<ion-item-sliding *ngFor="let chat of chatList" >
<button ion-item no-lines class="chat_content" (click)="openChat(chat.id, chat.receiver)">
<img class="circle-pic" src="{{chat.userImage}}" item-start>
<h2 class="content">{{chat.firstName}} {{chat.lastName}}</h2>
<p class="content">
<b *ngIf="!chat.isRead">{{chat.message}}</b>
<span *ngIf="chat.isRead">{{chat.message}}</span>~ {{chat.messageDate}}</p>
</button>
<ion-item-options side="left">
<button ion-button no-lines ion-button class="chat_buttons" color="secondary" (click)="favorite(item)">
<ion-icon class="chat_icons" name="star"></ion-icon>
</button>
<button ion-button class="chat_buttons" (click)="unread(item)">
<ion-icon class="chat_icons" name="disc"></ion-icon>
</button>
</ion-item-options>
<ion-item-options side="right">
<button ion-button no-lines class="chat_buttons" color="danger" (click)="share(item)">
<ion-icon class="chat_icons" name="trash"></ion-icon>
</button>
</ion-item-options>
</ion-item-sliding>
What I expect is a result like in the facebook messenger app wherein the latest conversation is put on top and only slides the other conversation down.
Code retrieving data Code for view
I faced this similar issue. I was able to fix this by adding trackBy in my *ngFor. https://angular.io/api/core/TrackByFunction
<ion-list *ngFor="let item of itemsList; trackBy: trackByFn">...</ion-list>
and in ts file:
trackByFn(index: number, item: any): number {
return item.serialNumber;
}
This line is causing the list to blink this.chatList = chatArray;
This line is replacing the entire variable. That causes Angular to think that the entire data has been changed and hence it reloads. What you can try doing, is pushing the last element into this.chatList
.
So instead of chatArray.push(data);
try doing this.chatList.push(data)
.
Read up on Angular Change Detection.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With