Skip to content
Advertisement

How can I convert scrollIntoView with smooth animation to a Promise?

I have to scrollIntoView a particular element smoothly and then do something.

Example

element.scrollIntoView({behavior: 'smooth'}).then(() => {
    // Do something here
})

I know that it can’t be done this way as native scrollIntoView doesn’t return a Promise. But, how do I achieve something like this?

I’m using Angular 7 BTW. So if there are any directives that could help me achieve this, it would be great.

Advertisement

Answer

You can work with prototypes, I think this could be a solution to your problem without download any npm packages

/* Extends Element Objects with a function named scrollIntoViewPromise
*  options: the normal scrollIntoView options without any changes
*/

Element.prototype.scrollIntoViewPromise = function(options){

  // "this" refers to the current element (el.scrollIntoViewPromise(options): this = el)
  this.scrollIntoView(options);
  
  // I create a variable that can be read inside the returned object ({ then: f() }) to expose the current element 
  let parent = this;
  
  // I return an object with just a property inside called then
  // then contains a function which accept a function as parameter that will be execute when the scroll ends 
  return { 
    then: function(x){
      // Check out https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API for more informations  
      const intersectionObserver = new IntersectionObserver((entries) => {
        let [entry] = entries;
        
        // When the scroll ends (when our element is inside the screen)
        if (entry.isIntersecting) {
        
          // Execute the function into then parameter and stop observing the html element
          setTimeout(() => {x(); intersectionObserver.unobserve(parent)}, 100)
        }
      });
      
      // I start to observe the element where I scrolled 
      intersectionObserver.observe(parent);
    }
  };
}


element.scrollIntoViewPromise({behavior: "smooth"}).then(()=>console.log("EHI!"));

I’ve created an example. I know it’s not an angular application, but it’s a good starting point. You just need to implement it (If you’re using typescript you have to create an interface which extends Element with the new function).

Advertisement