Home > Net >  Angular state not updating of array or bool
Angular state not updating of array or bool

Time:10-25

I have simple ngFor in which I am showing list

<a  *ngFor="let user of chatsLists" (click)="viewChat(user)">
    <div  [ngClass]="{'align-items-center': !user.isActiveChat}">
        <span >
            <img [src]="user.userid.userImage" alt="Avatar">
            <!-- <span ></span>
            <i></i> -->
        </span>
        <div >
            <h6 >{{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;
  }

}

CodePudding user response:

It may be caused because of the OnPush strategy. Perhaps because of the async nature of the http request and callback, the change detection has already happened.

I would suggest starting by changing your subscription strategy to using the async pipe.

For example:


  setChats() {
    this.chats$ = this.api.getAllChats().pipe(
      filter((res: any) => res.success),
      tap((res) => {
        this.chatsLists = res.data;
        this.chatdetails = this.chatsLists[0].messages;
        this.showChats = true;
      })
    );
    
    

Something like this. Then using {{ chats$ | aysnc }} on the HTML template.

The code above I suggested could do a lot of improving by typing variables and composing better streams, but you should definitely stick to the async pipe when using OnPush.

CodePudding user response:

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
    }
  })
}
  • Related