Search code examples
javascriptangularrxjschatngfor

Ngfor doesn't actualize on reloading page (Angular + RXJS)


Hi i'm building a chat app with angular for a school project i'm using firebase for my backend and i have an issue with my ngfor.

For exemple if i reload the page i will see nothing unless i hover my routerlink on my navbar. However sometime it will work after some time on the page without any action

When i recieve message i need to be on the page to see them ...

When i reload my page in first time my array is empty this may be what makes the ngfor bug array on reload.

I'm using ngOnInit() to subscribe :

messages: Message[];
  messageSubscription: Subscription;

  constructor(private messageService: MessageService, private router: Router) { 
    
  }

  ngOnInit(): void {
    this.messageSubscription = this.messageService.messageSubject.subscribe(
      (messages: Message[]) => {
        console.log(messages)
        this.messages = messages;
      }
    );
    this.messageService.getMessage();
    this.messageService.emitMessage();
  }

  ngOnDestroy(): void {
      this.messageSubscription.unsubscribe();
  }

This is my html template :

<div *ngFor="let message of messages" class="message-box">
    <img [src]="message.photoURL" class="profile-picture">
    <div class="content-box">
        <div class="information">
            <p class="username">{{message.displayName}}</p>
            <p class="date">{{message.createdAt | date: 'short'}}</p>
        </div>
        <p class="text">{{message.text}}</p>
    </div>
</div>

Here you can find my service with my getMessage() function and emitMessage():

  messages:Message[] = [];
  messageSubject = new Subject<Message[]>();
  constructor() { }

  emitMessage(){
    this.messageSubject.next(this.messages);
  }

  saveMessage(newMessage: Message){
    firebase.database().ref('/message').push(newMessage);
  }

  getMessage(){
    firebase.database().ref('/message')
      .on('value', (data) => {
        this.messages = data.val() ? Object.values(data.val()): [];
        this.emitMessage();
      });
  }

And this is the repo of my project: https://github.com/Zuxaw/AngularChatApp

If anyone has a solution I'm interested


Solution

  • Problem is, your firebase library is not Angular specific.

    This means you some times need to make sure its code, mostly its event callbacks, run within an Angular zone (google to read about it) to make sure a change detection 'tick' is invoked when data changes.

    message.service.ts

    import { Injectable, NgZone } from '@angular/core';
    
    // ...
    
    constructor(private zone: NgZone) { }
    
    // ..
    
    getMessage(){
      firebase.database().ref('/message')
        .on('value', (data) => {
          this.zone.run(() => {
            this.messages = data.val() ? Object.values(data.val()): [];
            this.emitMessage();
          });
        });
    }