javascript - bottom - scrollto angular 4
Autoscroll en angular 2 (10)
En lugar de escribir código en cada componente, agregué el siguiente código en un solo lugar:
<router-outlet (activate)="onActivate($event)"></router-outlet>
onActivate(e) {
window.scrollTo(0, 0);
}
Tengo un problema con Angular 2 en el que cambiar de una ruta a otra no se desplaza automáticamente a la parte superior de la nueva vista. Me doy cuenta de que Angular 1 permitía agregar una propiedad de autoscroll
a un elemento HTML, y otros habían presentado algunos javascript simples (como window.scroll(0, 0)
) para forzar que las vistas se desplazaran a la parte superior cuando se cargaban.
Sin embargo, no estoy seguro de cómo lograr esto con Angular 2. ¿Alguien sabe cómo lograr esto?
Estoy usando materiales sidenav y no pude obtener ninguna de las respuestas sugeridas para que funcionen para mí. Aquí está mi solución de trabajo:
import { Router, NavigationEnd } from ''@angular/router'';
...
constructor(
private router: Router,
) {
router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
document.querySelector(''.mat-sidenav-content'').scrollTop = 0;
}
}
}
He usado if (this.router.navigated) en ngOnInit de cada página para determinar si se usa o no window.scrollTo (0, 0). Esto cubrirá la mayoría de los casos de enrutamiento a la página, mientras deja la posición de desplazamiento donde debería estar si hace clic en el botón Atrás del navegador.
if(this.router.navigated) {
window.scrollTo(0, 0);
}
Los RC más nuevos (> = RC.3) no parecen exponer un changes
Observable, probablemente desde entonces se ha cambiado el nombre a https://angular.io/docs/ts/latest/api/router/index/Router-class.html#!#events-anchor o https://angular.io/docs/ts/latest/api/router/index/Router-class.html#!#events-anchor routerEvents .
Sus documentos absolutamente "fantásticos" no parecen proporcionar ninguna información sobre qué hace qué, así que supongo que te espera una pequeña Ruleta Rusa. O arroja una moneda o algo.
A partir de this respuesta, parece que los events
observables devuelven eventos relacionados con el estado de navegación:
router.events.subscribe(event:Event => { if(event is NavigationStart) { } // NavigationEnd // NavigationCancel // NavigationError // RoutesRecognized }
Para aquellos de ustedes que encuentren que window.scrollTo(0,0)
no funciona (supongo que por sidenav de diseño de material pero totalmente adivinando) use el método que se encuentra aquí: Javascript / CSS window.scrollTo (0,0) not working
Publiqué esto en el hilo del problema , pero lo volveré a publicar aquí.
Mi equipo ha estado usando lo que el equipo angular usa en este repositorio en angular.io. Solo haga un servicio e inyéctelo como de costumbre. Luego, en ngAfterViewInit en cada página que desea este comportamiento, simplemente llame a esto. [Scroll service variable name] .scrollToTop (). Finalmente, deberá agregar esto al principio de <body>
en index.html: <div id="top-of-page"></div>
Código de servicio:
import { Injectable, Inject } from ''@angular/core'';
import { PlatformLocation } from ''@angular/common'';
import { DOCUMENT } from ''@angular/platform-browser'';
import {fromEvent} from ''rxjs/observable/fromEvent'';
export const topMargin = 16;
/**
* A service that scrolls document elements into view
*/
@Injectable()
export class ScrollService {
private _topOffset: number | null;
private _topOfPageElement: Element;
// Offset from the top of the document to bottom of any static elements
// at the top (e.g. toolbar) + some margin
get topOffset() {
if (!this._topOffset) {
const toolbar = this.document.querySelector(''md-toolbar.app-toolbar'');
this._topOffset = (toolbar && toolbar.clientHeight || 0) + topMargin;
}
return this._topOffset;
}
get topOfPageElement() {
if (!this._topOfPageElement) {
this._topOfPageElement = this.document.getElementById(''top-of-page'') || this.document.body;
}
return this._topOfPageElement;
}
constructor(
@Inject(DOCUMENT) private document: any,
private location: PlatformLocation) {
// On resize, the toolbar might change height, so "invalidate" the top offset.
fromEvent(window, ''resize'').subscribe(() => this._topOffset = null);
}
/**
* Scroll to the element with id extracted from the current location hash fragment.
* Scroll to top if no hash.
* Don''t scroll if hash not found.
*/
scroll() {
const hash = this.getCurrentHash();
const element: HTMLElement = hash
? this.document.getElementById(hash)
: this.topOfPageElement;
this.scrollToElement(element);
}
/**
* Scroll to the element.
* Don''t scroll if no element.
*/
scrollToElement(element: Element) {
if (element) {
element.scrollIntoView();
if (window && window.scrollBy) {
// Scroll as much as necessary to align the top of `element` at `topOffset`.
// (Usually, `.top` will be 0, except for cases where the element cannot be scrolled all the
// way to the top, because the viewport is larger than the height of the content after the
// element.)
window.scrollBy(0, element.getBoundingClientRect().top - this.topOffset);
// If we are very close to the top (<20px), then scroll all the way up.
// (This can happen if `element` is at the top of the page, but has a small top-margin.)
if (window.pageYOffset < 20) {
window.scrollBy(0, -window.pageYOffset);
}
}
}
}
/** Scroll to the top of the document. */
scrollToTop() {
this.scrollToElement(this.topOfPageElement);
}
/**
* Return the hash fragment from the `PlatformLocation`, minus the leading `#`.
*/
private getCurrentHash() {
return this.location.hash.replace(/^#/, '''');
}
}
Puede ver aquí: https://angular.io/docs/ts/latest/api/router/index/Router-class.html#!#events-anchor , debe usar "router.events.subscribe" desde Angular 2.0.0
Así que una buena solución para escalar automáticamente en la parte superior de la página es tener un AppComponent como este:
import {Component} from ''@angular/core'';
import {Router, NavigationEnd} from "@angular/router";
@Component({
selector: ''app-root'',
templateUrl: ''./app.component.html''
})
export class AppComponent {
constructor(private router: Router) {
router.events.subscribe((val) => {
if (val instanceof NavigationEnd){
window.scrollTo(0,0);
}
});
}
}
Solución 100% probada por mí:
constructor(router:Router){
router.events.subscribe(() => {
window.scrollTo(0, 0);
}
Tuve el mismo problema. Basado en la respuesta de Gunter, encontré que el nuevo enrutador 2 RC.1 de Angular no expone un Observable directamente. En cambio, tiene una propiedad de changes
para ese propósito. La solución para RC.1 es:
this._router.changes.subscribe(() => {
window.scrollTo(0, 0);
});
actualizar
Actualmente no hay una manera automática.
Consulte también Error de texto mecanografiado angular 2 cuando usa la función de suscripción en un enrutador nuevo (rc 1)
Ver también https://github.com/angular/angular/issues/6595#issuecomment-244232725
class MyAppComponent { constructor(router: Router) { router.events.subscribe(s => { if (s instanceof NavigationEnd) { const tree = router.parseUrl(router.url); if (tree.fragment) { // you can use DomAdapter const element = document.querySelector("#" + tree.fragment); if (element) { element.scrollIntoView(element); } } } }); } }
actualizar
En el nuevo enrutador V3-beta.2 puede pasar un fragmento con enlaces de enrutador y navegación de enrutador
<a [routerLink]="..." fragment="top">
debería desplazarse hacia él, pero también agrega #top
a la URL (aún no probado)
Actualizar
Original
Hay un problema abierto que cubre este https://github.com/angular/angular/issues/6595
Una solución (mencionada en https://github.com/angular/angular/issues/6946 )
Inyecte el enrutador, suscríbase a los cambios de ruta e invoque el desplazamiento hacia arriba:
> = RC.x
router.changes.subscribe() => {
window.scrollTo(0, 0);
});
beta
router.events
.filter(e => e instanceof NavigationEnd)
.subscribe(() => {
window.scrollTo(0, 0);
});