简体   繁体   中英

Angular 5 anchor did not scroll

What I am trying to do is to create an anchor link. This link will navigate to a specific scroll point in my page. I have Angular version 5.

Html:

<mat-list>
     <mat-list-item><a [routerLink]="['/']"> Intro </a></mat-list-item>
     <mat-list-item><a [routerLink]="['/']" fragment="mobile"> Mobile </a></mat-list-item>     
     ...
</mat-list>

In home.componets.ts:

export class HomeGrComponent implements OnInit {
    private fragment: string;

constructor(private route: ActivatedRoute) { }

ngOnInit() {        
    this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
}

ngAfterViewInit(): void {
    try {
        setTimeout(()=> {
            document.querySelector('#' + this.fragment).scrollIntoView();
        }, 1000);

    } catch (e) { }
  }    
}

I took this code from this question but it doesn't work. Url is changed to

http://localhost:4200/#mobile

but it didn't scroll to my point. Also in console there is an error:

Cannot read property 'scrollIntoView' of null 

What can be possible goes wrong? If you need some additional information please ask me to reply. Also it could be great the scroll navigates smoothly (optional).

You can use the following Code:

import { Component, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { filter } from 'rxjs/operators';
import { Subscription } from 'rxjs';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnDestroy {
  private sub: Subscription;

  constructor(activeRoute: ActivatedRoute) {
    this.sub = activeRoute.fragment.pipe(filter(f => !!f)).subscribe(f => document.getElementById(f).scrollIntoView());
  }

  public ngOnDestroy(): void {
    if(this.sub) this.sub.unsubscribe();
  }
}

Working example and Code behind

The reason why it's not working is that ngAfterViewInit is being called before the Observable is resolved, and therefore this.fragment is null, so no element is found

ngOnInit() {        
    this.route.fragment.subscribe(fragment => {
        this.fragment = fragment;
    });
}

ngAfterViewInit(): void {
    let interval = setInterval(()=> {
        let elem = document.getElementById(this.fragment);
        if(elem) {
            elem.scrollIntoView();
            clearInterval(interval);
        }
    }, 1000);  
}

Another option is to use setTimout() . So you don't need clearInterval(). You can also access the fragment with the help of the ActivatedRoute

constructor(private route: ActivatedRoute) {}

ngAfterViewInit(): void {
           setTimeout(() => document.querySelector(this.route.snapshot.fragment).scrollIntoView(), 1000);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM