Babyburger
Babyburger

Reputation: 1830

Angular - wait until DOM updated view for specific variable

I am creating a chat application. On changing a chat window, I want the scrollbar to navigate to the bottom in order to view the most recent messages immediately. My code to do this:

ngAfterViewInit(): void {
    this.updateMessageExchange.subscribe((interlocutor: MessageExchange) => {
        this.activeChatExchange = interlocutor; // this triggers a view change in the html
        setTimeout(() => {
            console.log('sleep');
            this.scrollToBottom();
        }, 100);

    });
}

private scrollToBottom(): void {
    this.chatBoard.nativeElement.scrollTop = this.chatBoard.nativeElement.scrollHeight;
}

corresponding relevant html:

<ng-container *ngFor="let message of activeChatExchange.messages">

This works, but I had to introduce a sleep to make it work. Without the sleep, the update of scrollTop happens too quick and the window on the next page will not be updated to scroll to the bottom. This has nothing to do with the value of scrollHeight either. If I set a really high static number like 999999 it will still not scroll to the bottom.

So the issue is that this solution is not very good. A too high number for the sleep puts an artificial delay in my application, making it appear sluggish and too low a number may cause slow browsers to not be scrolled down after loading.

I would like to subscribe to when the DOM event change is finished, but only for a change in activeChatExchange. How should I approach this?

Upvotes: 1

Views: 1567

Answers (1)

Babyburger
Babyburger

Reputation: 1830

I think I found the solution, with help from Angular - Wait for ngFor to update DOM

I'm not entirely sure if this qualifies as a proper solution, but setting the sleep to 0 apparently works because the function timeout starts counting after rendering, which is what I want.

So my code becomes

    this.updateMessageExchange.subscribe((interlocutor: MessageExchange) => {
        this.activeChatExchange = interlocutor;
        setTimeout(() => {
            this.scrollToBottom();
        }, 0);
    });

Upvotes: 4

Related Questions