Issue
I have this code in angular application
html:
<input type="button" value="Add" (click)="addItems()" />
<div id="messageContainer" style="width:200px; height:300px; overflow-y:scroll;" #scrollMe >
<div *ngFor="let i of items">
{{i}}
</div>
</div>
component.ts:
items: string[] = [];
count = 20;
@ViewChild('scrollMe') private scrollContainer: ElementRef;
ngOnInit() {
this.addInitialItems();
}
addItems() {
const currentPosition = this.scrollContainer.nativeElement.scrollTop;
this.items.unshift(this.count.toString());
this.count++;
this.scrollContainer.nativeElement.scrollTop = currentPosition;
}
addInitialItems() {
for (let i = 0; i <= this.count - 1; i++) {
this.items.unshift(i.toString());
}
// this is not working
this.scrollContainer.nativeElement.scrollTop = this.scrollContainer.nativeElement.scrollHeight;
}
Initially messageContainer div should be filled with multiple items, with div scrolled to bottom, once user click an Add button it will add an item to the top of the messegaes list and should maintain the scroll position.
Retaining scroll position is done with
const currentPosition = this.scrollContainer.nativeElement.scrollTop;
//add new item
this.scrollContainer.nativeElement.scrollTop = currentPosition;
But, initial scrolling to bottom of div is not working,
this.scrollContainer.nativeElement.scrollTop = this.scrollContainer.nativeElement.scrollHeight;
scrollTop
value is 0 even after setting it,
How to get this scrolled to bottom of the div initially?
Solution
@ViewChild objects are not fully defined until the 'ngAfterViewInit' lifecycle hook. Try moving your method call to that hook.
ngAfterViewInit() {
this.addInitialItems();
}
Something else you might want to try is binding to scrollTop directly in the template, so you won't have to access the nativeElement at all.
<input type="button" value="Add" (click)="addItems()" />
<div id="messageContainer" style="width:200px; height:300px; overflow-y:scroll;" [scrollTop]="myScrollVariable">
<div *ngFor="let i of items">
{{i}}
</div>
</div>
In your component you could then simply write something like
this.myScrollVariable = currentPosition;
Instead of modifying the DOM element directly. Granted, if you wanted to initialize the scroll to the scrollHeight, you'd probably still need to use ViewChild to access the nativeElement and get that attribute (although personally, I would just initialize scrollTop to some absurdly high number like 99999999, anything greater than scrollHeight will be the same as the exact scrollHeight).
If moving the method call to ngAfterViewInit doesn't work, try setting scrollTop inside a setTimeout function. Sometimes the Angular change detector is weird about picking up changes to the native DOM and as a workaround you can escape the change outside the regular angular event loop with a timeout.
setTimeout(()=>{ this.scrollContainer.nativeElement.scrollTop = whatever; },1)
Answered By - diopside
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.