Lazy Loading and ScrollIntoView() Angular2(version 7)
Asked Answered
T

2

0

I'm trying to show a component when first load the page with lazy loading that only load the content if it's in the view. For example: - There are 10 components on the page and I want to show/scroll to the component number 7 on first load with lazy loading(for performance).

How do I do this correctly? Challenge here is because these components are lazy loading and have huge images that messed up the scrollIntoView() and scrolled too much to the top passed the component.

  • I've tried these approaches but no luck :(
  • Put a reference to the component 7:
    1. Scroll to that component by scrollIntoView(). Use window.scrollBy(0, -100) for the navigation bar.
    2. Get the component offsetTop and use window.scrollTo(0, targetComponent.offsetTop - 100);
    3. Both approaches above but with a setTimeout of 2s - 5s didn't work either.
    4. Use scrollIntoView() to scroll to the component, wait couple seconds with setTimeout and use scrollIntoView() again with window.scrollBy(0, -100) also didn't work.
    5. Give the image container a fixed height (ie: 500px), so the lazy loading images will fill up the container, but what if the component is being used on other pages get a bigger size image (ie: 1200px) will messed up the UI.
    6. The window.scrollY, window.pageYOffset, getBoundingClientRect().top and these values to get the height I need are different from the code compared from the console.log of the code vs the browser values so my calculations are incorrect.
    7. scrollIntoView({ block: 'start' }) and window.scrollBy(0, -100) also didn't work too. It scrolled too the top and passed the navbar even though I used window.scrollBy(0, -100). Also tried the setTimeout with this too.

Something like this that I tried but the component still scroll too much to the top.

<div>Div 1</div>
<div>Div 2</div>
<div>Div 3</div>
<div>Div 4</div>
<div>Div 5</div>
<div>Div 6</div>
<div #target>Target Div 7</div>
<div>Div 8</div>
<div>Div 9</div>
<div>Div 10</div>
export class BBQComponent implements AfterViewInit {
  @ViewChild("target") targetElement: ElementRef;

  ngAfterViewInit() {
    setTimeout(_ => {
     this.targetElement.nativeElement.scrollIntoView({block: "start"});
     window.scrollBy(0, -100);
    }, 2000); 
  }
}

I expect the page to show the component on first visit just below the navigation bar (about 100px in height). I have searched for the solutions and tried out different things but still stuck at this.

Is there something that I missed to get this feature scrollIntoView to work with lazy loading content? Thanks!!

Tref answered 25/6, 2019 at 22:36 Comment(0)
T
0
  • Best solution for now

export class BBQComponent implements AfterContentChecked {
  @ViewChild("target") targetElement: ElementRef;
  scrolled = false; // To avoid multiple scrolls because ngAfterContentChecked

  ngAfterContentChecked() { // Changed from ngAfterViewInit()
    if(!scrolled) {
      const target = this.targetElement.nativeElement;
      target.scrollIntoView({block: "start"}); // Scroll to the component

      // After scrolled, wait for the browser to figure out where the 
      // component is after lazy loading is done. Scroll again.
      setTimeout(_ => {
       target.scrollIntoView({block: "start"});
       window.scrollBy(0, -100); // Nav's height
       this.scrolled = true;
      }, 1000); // Adjust wait time as needed
    }
  }
}
Tref answered 30/6, 2019 at 17:19 Comment(0)
S
0

Dang.

You should ensure about compatibility.

If you read here Doc notice that options like {block : "start"} is not really supported for any browser.

Bytheway, I dont really know if your problem is more related with lazy loading implementation or scrollIntoView. If it is about lazy loading I strongly recommend you to use JQuery Lazy loading that will prevent you from headaches with his easy configuration.

Starve answered 30/6, 2019 at 17:31 Comment(1)
Hi Sam, thank you for your answer. Good point on the {block : "start"} option. For the JQuery Lazy loading, isn't it a bad practice to use any JQuery in an Angular application?Tref

© 2022 - 2024 — McMap. All rights reserved.