20

For a side project of mine, I want to implement a chat stream where new message is added to the bottom and the windows should scroll to the bottom to display the latest message.

In order to do that, I have opted to use ViewChildren on the component to find the last message(latest) and use scrollIntoView on the nativeElement.

In order not to call the method by accessing the DOM API directly nativeElement.scrollIntoView(). I believe I will need to use renderer.invokeElementMethod(nativeElement, 'scrollIntoView').

Problem is renderer is deprecated in favor of renderer2 and I cant seem to find alternative for the method invokeElementMethod in renderer2.

Question is, is there a method that I missed in renderer2 that do just that? or we have a new way doing invoking element method now?

Zameer Ansari
  • 28,977
  • 24
  • 140
  • 219
endyjasmi
  • 345
  • 1
  • 2
  • 9

2 Answers2

18

You can use selectRootElement method of Renderer2.

For example:

constructor(private renderer: Renderer2) {}

this.renderer.selectRootElement('#domElementId').scrollIntoView()

, where domElementId is id='domElementId' in your html


UPDATE

Supply a Second Argument for selectRootElement as per Angular's Official Documentation as it is used to preserve your content

selectRootElement(selectorOrNode: any, preserveContent?: boolean): any

this.renderer
  .selectRootElement'#domElementId', true)  // Supply true for the 2nd arg to make sure your content is preserved.
  .scrollIntoView()                      // Or ({ behavior: 'smooth' }) for smooth scrolling
KShewengger
  • 7,853
  • 3
  • 24
  • 36
seytzhan
  • 527
  • 5
  • 7
  • I would avoid using `Renderer2` as it's poor documented for unit testing...for testing you'' end up writing your own renderer – DAG Nov 30 '17 at 09:56
  • This did not work for me with Renderer2. The element was selected, but calling `scrollIntoView` just removed that section from the dom!! I had to revert to the ViewChild method of calling it directly – Drenai Jan 07 '18 at 23:02
  • 2
    I don't know how this has 10 upvotes. selectRootElement deletes all the child nodes of the selected element. It is only used for selecting the root angular element, and not for selecting specific elements See https://github.com/angular/angular/issues/19554#issuecomment-341848166 – Drenai Jan 25 '18 at 13:17
  • @Drenai this function's prototype has a parameter to preserve content selectRootElement(selectorOrNode: any, preserveContent?: boolean): any – The Segfault Nov 12 '18 at 08:31
  • 1
    @TheSegfault It's purpose is to select the **root** element, not a specific element. Misuse at your own risk:-) API Documentation `..prepare an element to be bootstrapped as a root element, and return the element instance`. https://angular.io/api/core/Renderer2#selectrootelement – Drenai Nov 12 '18 at 11:15
  • This may help if you are a <3 of `elementRef` : https://stackblitz.com/edit/angular-ivy-oi2ydk?file=src/app/app.component.ts – Rinold Jul 23 '21 at 14:04
0

Let's answer this by an exapmple:

In case we have a view like this:

<input #inp1 type="text" placeholder="focus on me" />

Inside ngAfterViewInit(), it needs to be given focused like this:

this.renderer.selectRootElement("inp1").scrollIntoView();
Zameer Ansari
  • 28,977
  • 24
  • 140
  • 219
  • @Brian Your inputs are welcome! Can you post the code which worked for you as an answer, so others can benefit? – Zameer Ansari Jan 08 '18 at 09:46
  • https://stackblitz.com/edit/angular-ivy-oi2ydk?ctl=1&embed=1&file=src/app/app.component.ts here is the full example :) – Rinold Jul 23 '21 at 13:58