dota2pro
dota2pro

Reputation: 7856

How to scroll to bottom of an element in NgFor while adding element?

import { Component, Input, AfterViewInit, ViewChild } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1>

  <div #commentDetailWrapper style="height: 100px; border: 1px solid; width: 100px; overflow-y:scroll ">

<div *ngFor="let axe of axes"><button>Filler</button></div>

  </div>
  <button (click)='add()'>Add More</button>


  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent implements AfterViewInit {
  @Input() name: string;
  @ViewChild('commentDetailWrapper', { static: false }) commentDetailWrapper;

  axes = Array(10);

  add() {
    this.axes.push(Array(1));
    const el: HTMLDivElement = this.commentDetailWrapper.nativeElement;
    el.scrollTop = el.scrollHeight;
  }

  ngAfterViewInit() {
    const el: HTMLDivElement = this.commentDetailWrapper.nativeElement;
    el.scrollTop = el.scrollHeight;
  }

}

This works on Default it scrolls to the last element how do I scroll to bottom when I add a new element by clicking on the add More button

Here is the problem Working Demo on Stackblitz

Desired Result: scroll to bottom on clicking add more button

Upvotes: 1

Views: 1861

Answers (1)

ajai Jothi
ajai Jothi

Reputation: 2294

Executing the scroll after a timeout solves the problem. Since the view is not updated when you try to scroll.

Solution 1: using AfterViewChecked hook,

export class HelloComponent implements AfterViewInit, AfterViewChecked {
added:boolean;
 ...
   add() {
    this.axes.push(Array(1));
    this.added = true;
  }

  ngAfterViewChecked() {
   // run only when new axe is added
   if(this.added) {
    const el: HTMLDivElement = this.commentDetailWrapper.nativeElement;
    el.scrollTop = el.scrollHeight;
    this.added = false;
   }
  }
...
}

Solution 2: using setTimeout,

...
add() {
   this.axes.push(Array(1));
   const el: HTMLDivElement = this.commentDetailWrapper.nativeElement;
   setTimeout(() => {
     el.scrollTop = el.scrollHeight;
   });
}
...

Solution 1a: Separating the component and make the input data immutable. Used ChangeDetectionStrategy.OnPush for the implementation

https://stackblitz.com/edit/angular-2zjf4a

Upvotes: 1

Related Questions