Search code examples
angularangular-dynamic-components

How can I scroll into view for dynamic loaded content in Angular 11?


In my app I need to load HTML from a file. This file contains plain HTML code and come anchors. Now, when I click on such an anchor I would like to scroll this anchor into view. Therefore I wrote the following code:

HTML code

<div class="section">
    <a href="#distancegroup">DistanceGroup</a>
</div>

...

<h3 id="distancegroup">Distancegroup</h3>

Component

@Component({
    selector: 'loadHTMLContent',
    template: `<span [innerHTML]="content"></span>`,
})
export class LoadHTMLContentComponent implements OnInit {
    @Input('file') file: string;
    public content: any;

    constructor(private http: HttpClient, private sanitizer: DomSanitizer, private ref: ElementRef) {}

    ngOnInit() {
        if (!this.file) return;

        this.http.get(this.file, { responseType: 'text' }).subscribe(response => {
            this.content = this.sanitizer.bypassSecurityTrustHtml(response);
        });
    }

    ngAfterViewInit() {
        setTimeout(() => {
            const anchors = [...this.ref.nativeElement.querySelectorAll('a')];
            anchors.forEach(a =>
                a.addEventListener('click', e => {
                    e.preventDefault();
                    a.scrollIntoView({ behavior: 'smooth', block: 'center' });
                })
            );
        }, 1000);
    }
}

The problem is now that the scrollIntoView wont work and I have really no idea what is wrong with my code. Does anybody has an idea or solution, please?

Or maybe is there a possibility to create a real Angular component from the HTML string, so that the use of the router is possible too?


Solution

  • I think you're trying to scroll the anchor into view instead of the target element. So try to change like this (see my similar example here):

    anchors.forEach(a =>
      a.addEventListener("click", e => {
        const el = this.ref.nativeElement.querySelector(a.getAttribute('href'));
    
        e.preventDefault();
        el.scrollIntoView({ behavior: "smooth", block: "center" });
      })
    );