top bottom javascript angular angular2-routing

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 }



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