3

I have a parent component that has several components inside it:

<div  class="mx-sm-auto mb-5 px-0 container">
  <app-set-vehicle-details id="step1" #step1 (step1Finished)="enableStep2()"></app-set-vehicle-details>
  <app-product-selection id="step2" *ngIf="step2Enabled"></app-product-selection>
  <app-product-additional id="step3" *ngIf="step3Enabled"></app-product-additional>
</div>

All the child elements emmit a finished once they get unlocked and you can proceed to next step. So you enable the next step as follows:

step2Enabled = false;

enableStep2() {
  this.step2Enabled = true;
  this.scrollToElement('step2');
}

scrollToElement(id: string): void {
  const element = document.querySelector('#' + id);
  if (element) {
    element.scrollIntoView({behavior: 'smooth', block: 'start', inline: 'nearest'});
  }
}

So step2 component gets visible, but scroll to it it's not working. I assume this is happening because the visibility of the second component didn't to true before the scrollToElement call, because it works once the component is visible.

How can I make this behavior to make this work?

Thanks!

7
  • You're scrolling to something which doesn't yet exist. It will only exist on the next render. Commented Mar 9, 2020 at 15:55
  • Yes, that's why I was suspecting. How can I achieve that behavior? (That's my real question indeed...) Commented Mar 9, 2020 at 15:56
  • The easiest way would be to toggle display: none css style instead of *ngIfing those elements. Commented Mar 9, 2020 at 15:59
  • Not working neither... Commented Mar 9, 2020 at 16:08
  • I solved it adding a delay of 50 ms.... Commented Mar 9, 2020 at 16:10

2 Answers 2

2

You can monitor the presence of the child component with ViewChildren, by subscribing to the QueryList.changes event.

First, set a template reference variable on the child component:

<app-product-selection #step2 *ngIf="step2Enabled"></app-product-selection>

Then use that variable to refer to the component host element in code, and subscribe to the QueryList.changes event in ngAfterViewInit. When the event is triggered, scroll the component into view:

@ViewChildren("step2", { read: ElementRef }) step2List: QueryList<ElementRef>;

ngAfterViewInit() {
  this.step2List.changes.subscribe(() => {
    if (this.step2List.length > 0) {
      (this.step2List.first.nativeElement as HTMLElement).scrollIntoView();
    }
  });
}

See this stackblitz for a demo.

Sign up to request clarification or add additional context in comments.

Comments

-2

My solution is this:

enableStep2() {
   this.step2Enabled = true;
   setTimeout(() => {
     this.scrollToElement('step2');
   });
}

This waits until step2 is visible. So perfect!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.