Issue
I have simple ngFor in which I am showing list
<a class="list-group-item " *ngFor="let user of chatsLists" (click)="viewChat(user)">
<div class="media chat-list-text py-1" [ngClass]="{'align-items-center': !user.isActiveChat}">
<span class="avatar avatar-md mr-2">
<img [src]="user.userid.userImage" alt="Avatar">
<!-- <span class="avatar-status-{{user.status}}"></span>
<i></i> -->
</span>
<div class="media-body">
<h6 class="list-group-item-heading mb-1">{{user.userid.userName}}
</h6>
</div>
</div>
</a>
and function from api I am getting data
chatsLists: any; //also tried with chatsLists = [];
getChats() {
this.api.getAllChats().subscribe((res: any) => {
if (res.success) {
this.chatsLists = res.data;
this.chatdetails = this.chatsLists[0].messages;
this.showChats = true;
}
else {
}
})
}
Its not updating the ngFor loop and if I click on any input on screen and remove hover from it then its showing the loop state is not updating that’s mean
Also I try to just place in html
<p *ngIf="showChats">Show </p>
and in my function I change the bool value but in console I can see its showing true but its not reflecting in html file
full code of component.ts
this.showChats = true;
import { Component, ViewChild, ElementRef, OnInit, ChangeDetectionStrategy, Renderer2, Inject, OnDestroy, ChangeDetectorRef } from '@angular/core';
import { ChatService } from './chat.service';
import { Chat, UsersChat } from './chat.model';
import { DOCUMENT } from '@angular/common';
import { ConfigService } from 'app/shared/services/config.service';
import { Subscription } from 'rxjs';
import { ApiService } from 'app/services/api/api.service';
@Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
styleUrls: ['./chat.component.scss'],
providers: [ChatService]
})
export class ChatComponent implements OnInit, OnDestroy {
chats: Chat[] = [];
activeChat: UsersChat;
usersChat: UsersChat[] = [];
activeChatUser: string;
activeChatUserImg: string;
loggedInUserImg: string;
newMessage = "";
searchQuery: string = '';
placement = "bottom-right";
isContentOverlay = false;
activeIndex = 0;
chatdetails = [];
showChats: any;
public config: any = {};
layoutSub: Subscription;
chatsLists: any;
messages = new Array();
item: number = 0;
constructor(private api: ApiService, private elRef: ElementRef, private renderer: Renderer2,
@Inject(DOCUMENT) private document: Document,
private configService: ConfigService, private cdr: ChangeDetectorRef,
private chatService: ChatService) {
this.config = this.configService.templateConf;
this.usersChat = chatService.usersChat;
this.activeChat = chatService.usersChat.find(_ => _.isActiveChat);
this.chats = this.activeChat.chats;
this.activeChatUser = this.activeChat.name;
this.activeChatUserImg = this.activeChat.avatar;
this.loggedInUserImg = "assets/img/portrait/small/avatar-s-1.png"
this.renderer.addClass(this.document.body, "chat-application");
}
ngOnInit() {
this.getChats();
}
ngOnDestroy() {
if (this.layoutSub) {
this.layoutSub.unsubscribe();
}
this.renderer.removeClass(this.document.body, "chat-application");
}
getChats() {
this.api.getAllChats().subscribe((res: any) => {
if (res.success) {
this.chatsLists = res.data;
this.chatdetails = this.chatsLists[0].messages;
this.showChats = true;
}
else {
}
})
}
//send button function calls
onAddMessage() {
if (this.newMessage != "") {
this.activeChat.chats.push({
isReceived: false,
time: "",
messages: [this.newMessage],
messageType: 'text'
})
this.newMessage = "";
}
}
viewChat(chat: UsersChat) {
this.usersChat.forEach(chat => {
if (chat.userId === this.activeChat.userId) {
chat.isActiveChat = false;
}
})
this.activeChat = chat;
this.activeChat.isActiveChat = true;
this.chats = this.activeChat.chats;
this.activeChatUser = this.activeChat.name;
this.activeChatUserImg = this.activeChat.avatar;
this.isContentOverlay = false;
}
onSidebarToggle() {
this.isContentOverlay = true;
}
onContentOverlay() {
this.isContentOverlay = false;
}
}
Solution
ChangeDetectionStrategy.OnPush
means that if you make async calls outside the component you have to tell the component to update. Are you sure you want it? If you do still want to have it add changeDetectorRef to your constructor and then have it mark the component as ready for change detection:
constructor(..., private changeDetectorRef: ChangeDetectorRef) {
And then in your getChats function you have
getChats() {
this.api.getAllChats().subscribe((res: any) => {
if (res.success) {
this.chatsLists = res.data;
this.chatdetails = this.chatsLists[0].messages;
this.showChats = true;
this.changeDetectorRef.markForCheck(); //Add it here
}
})
}
Answered By – Mathew Berg
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0