Lo que estoy intentando hacer es crear un enlace de anclaje. Este enlace navegará a un punto de desplazamiento específico en mi página. Tengo la versión 5 de Angular.

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>

En 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) { }
  }    
}

Tomé este código de esta pregunta pero no funciona. La URL se cambia a

http://localhost:4200/#mobile

Pero no se desplazó a mi punto. También en la consola hay un error:

Cannot read property 'scrollIntoView' of null 

¿Qué puede ser posible que salga mal? Si necesita información adicional, pida que le responda. También podría ser genial que el scroll navegue sin problemas (opcional).

1
Vasilis Greece 22 feb. 2018 a las 12:36

2 respuestas

La mejor respuesta

Puede utilizar el siguiente código:

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();
  }
}

ejemplo y Código subyacente

2
Markai 22 feb. 2018 a las 10:27

La razón por la que no funciona es que se llama a ngAfterViewInit antes de que se resuelva el Observable y, por lo tanto, this.fragment es nulo, por lo que no se encuentra ningún elemento.

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);  
}
1
Nikola Gavric 22 feb. 2018 a las 10:14