28
Scrolling to an Element Only After It Appears using Angular
This is an evolution of my previous article. Let's suppose you have the following requirement:
In a long page, wait for a specific HTML Element to appear, and only after its generation scroll to it.
It looks simple right? But imagine that this Element exibition could take some time, for instance, it could be a grid with some information provided from a web service, or some data from a slow SQL query. Nevertheless, there's no reason to scroll before the data is already shown. So how can we do it? My goals are:
- Create a button that will generate a grid at the bottom of a long page;
- After the button is clicked, some mechanism is needed to simulate random time;
- Scroll to the grid only after it was added to the page.
comment: The table to be scrolled is not added to the page by default. This is possible by using a *ngIf
statement. As you can see bellow, this is achieved by setting the variable showTable
to false at startup. This DOM concept is important to understand, because if you have decided to use hidden
attibute instead of *ngIf
strategy, the table would be already on your page and DOM, the only thing is that it would be hidden.
Let's create a button that will call a fake backend. Let's also add a Spinner just to illustrate time. Here is a good place where you can find cool CSS Spinners to add to your page.
Bellow you can see that after clicking the button a function named waitAndGoDown()
is called. This will be described in details next.
<div style="text-align: center">
<button (click)="waitAndGoDown()">Wait Random time and go Down</button>
<p>
<div *ngIf="showSpinner" class="loader">Loading...
</div>
</div>
By default, after clicking the button we want to turn the Spinner on and wait some random time until finally exibit the grid. A fake backend can be simulated by using a setTimeout
method. Look inside waitAndGoDown()
function:
As it can be seen on Stackblitz, simulateBackend()
function uses a random setTimeout
limited to 5 seconds to randomize the return of the fake Backend. This means that after a while the Spinner is turned off and the grid is allowed to appear.
comment: Remember that everything is asynchronous, as a result, the program doesn't wait simulateBackend
to return to invoke waitForElement
. That's why there's a need for some mecanism to monitor when the table appears (or when the DOM mutates) and eventually when to scrool to it.
Check bellow how the monitoring is done line by line, notice that the id 'myTable'
of the table to be presented is passed as an argument.
Lines 39-43: Checks if the element is already there. If it is, scroll to it and return.
Line 44: Creates an observer that monitors nodes added to the DOM. Every time the DOM mutates, the changes are observed.
Lines 47-54: It checks if the newest mutation contains the element we are looking for (the table!). If it is, scroll to it.
Lines 56-59: Defines what kind of nodes are going to be observed (the entire childList of the root component)
The function that does the scrolling is one of the options presented here.
There's also a Stackblitz with this example.
Hope this can help someone!
28