En mi aplicación Angular 2 cuando me desplazo hacia abajo en una página y hago clic en el enlace en la parte inferior de la página, cambia la ruta y me lleva a la página siguiente, pero no se desplaza hacia la parte superior de la página. Como resultado, si la primera página es larga y la segunda página tiene pocos contenidos, da la impresión de que la segunda página carece de contenido. Dado que los contenidos son visibles solo si el usuario se desplaza hacia la parte superior de la página.
Puedo desplazar la ventana a la parte superior de la página en ngInit del componente pero, ¿hay alguna solución mejor que pueda manejar automáticamente todas las rutas en mi aplicación?
RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })
Respuestas:
Puede registrar una escucha de cambio de ruta en su componente principal y desplazarse hacia arriba en los cambios de ruta.
fuente
window.scrollTo(0, 0)
es unadocument.body.scrollTop = 0;
OMI más concisa y más legible.$("body").animate({ scrollTop: 0 }, 1000);
lugar dewindow.scrollTo(0, 0)
animar el desplazamiento suave hacia arribaAngular 6.1 y posterior :
Angular 6.1 (lanzado el 25-07-2018) agregó soporte incorporado para manejar este problema, a través de una función llamada "Restauración de la posición de desplazamiento del enrutador". Como se describe en el blog oficial de Angular , solo necesita habilitar esto en la configuración del enrutador de esta manera:
Además, el blog dice "Se espera que esto se convierta en el predeterminado en una versión principal futura". Hasta ahora, esto no ha sucedido (a partir de Angular 8.2), pero eventualmente no necesitará hacer nada en su código, y esto simplemente funcionará correctamente de fábrica.
Puede ver más detalles sobre esta característica y cómo personalizar este comportamiento en los documentos oficiales .
Angular 6.0 y anterior :
Si bien la excelente respuesta de @ GuilhermeMeireles soluciona el problema original, presenta una nueva, al romper el comportamiento normal que espera cuando navega hacia atrás o hacia adelante (con los botones del navegador o mediante la Ubicación en el código). El comportamiento esperado es que cuando navega de regreso a la página, debe permanecer desplazado hacia abajo a la misma ubicación que cuando hizo clic en el enlace, pero desplazarse a la parte superior al llegar a cada página obviamente rompe esta expectativa.
El siguiente código expande la lógica para detectar este tipo de navegación al suscribirse a la secuencia PopStateEvent de Location y omitir la lógica de desplazamiento hacia arriba si la página recién llegada es el resultado de tal evento.
Si la página desde la que navega es lo suficientemente larga como para cubrir toda la ventana gráfica, la posición de desplazamiento se restaura automáticamente, pero como @JordanNelson señaló correctamente, si la página es más corta, debe realizar un seguimiento de la posición de desplazamiento original y restaurarla. explícitamente cuando vuelves a la página. La versión actualizada del código cubre este caso también, siempre restaurando explícitamente la posición de desplazamiento.
fuente
body
?Desde Angular 6.1, ahora puede evitar la molestia y pasar
extraOptions
a suRouterModule.forRoot()
como segundo parámetro y puede especificarscrollPositionRestoration: enabled
decirle a Angular que se desplace hacia arriba cada vez que cambie la ruta.Por defecto lo encontrarás en
app-routing.module.ts
:Documentos oficiales angulares
fuente
Puede escribir esto de manera más sucinta aprovechando el
filter
método observable :Si tiene problemas para desplazarse hacia la parte superior al usar el material angular de Sidenav 2, esto será útil. La ventana o el cuerpo del documento no tendrán la barra de desplazamiento, por lo que debe obtener el
sidenav
contenedor de contenido y desplazar ese elemento; de lo contrario, intente desplazar la ventana por defecto.Además, Angular CDK v6.x tiene un paquete de desplazamiento ahora que podría ayudar con el manejo del desplazamiento.
fuente
document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;
Si tiene renderizado del lado del servidor, debe tener cuidado de no ejecutar el código utilizando
windows
en el servidor, donde esa variable no existe. Resultaría en la ruptura del código.isPlatformBrowser
es una función que se usa para verificar si la plataforma actual donde se representa la aplicación es un navegador o no. Le damos lo inyectadoplatformId
.También es posible verificar la existencia de variables
windows
, para estar seguro, así:fuente
PLATFORM_ID
enconstructor
y dar este valor como parámetro en elisPlatformBrowser
método?isPlatformBrowser
es una función y siempre será veraz. Lo he editado ahora.solo hazlo fácil con la acción de hacer clic
en su componente principal html haga referencia #scrollContainer
en el componente principal .ts
fuente
scrollContainer
primer nodo, puede que tenga que cavar un poco en el objeto, para mí lo que realmente trabajadas fuescrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0
Angular introdujo recientemente una nueva característica, dentro del módulo de enrutamiento angular realiza cambios como a continuación
fuente
La mejor respuesta reside en la discusión de Angular GitHub ( Cambiar la ruta no se desplaza hacia arriba en la nueva página ).
app.component.html
app.component.ts
Créditos completos a JoniJnm ( publicación original )
fuente
Puede agregar el enlace del ciclo de vida AfterViewInit a su componente.
fuente
A partir de Angular 6.1, el enrutador proporciona una opción de configuración llamada
scrollPositionRestoration
, que está diseñada para satisfacer este escenario.fuente
Si necesita simplemente desplazarse por la página hacia arriba, puede hacerlo (no es la mejor solución, pero es rápido)
fuente
Aquí hay una solución que se me ocurrió. Emparejé la estrategia de ubicación con los eventos del enrutador. Usando LocationStrategy para establecer un valor booleano para saber cuándo un usuario atraviesa actualmente el historial del navegador. De esta manera, no tengo que almacenar un montón de URL y datos de desplazamiento en y (que de todos modos no funciona bien, ya que cada información se reemplaza en función de la URL). Esto también resuelve el caso límite cuando un usuario decide mantener presionado el botón de retroceso o avance en un navegador y retrocede o reenvía varias páginas en lugar de solo una.
PD: solo he probado en la última versión de IE, Chrome, Firefox, Safari y Opera (a partir de esta publicación).
Espero que esto ayude.
fuente
Esta solución se basa en la solución de @ FernandoEcheverria y @ GuilhermeMeireles, pero es más concisa y funciona con los mecanismos de popstate que proporciona Angular Router. Esto permite almacenar y restaurar el nivel de desplazamiento de múltiples navegaciones consecutivas.
Almacenamos las posiciones de desplazamiento para cada estado de navegación en un mapa
scrollLevels
. Una vez que hay un evento popstate, el ID del estado que está a punto de ser restaurado es suministrada por el router Angular:event.restoredState.navigationId
. Esto se usa para obtener el último nivel de desplazamiento de ese estadoscrollLevels
.Si no hay un nivel de desplazamiento almacenado para la ruta, se desplazará a la parte superior como era de esperar.
fuente
scrollTop
vsscrollY
.Además de la respuesta perfecta proporcionada por @Guilherme Meireles como se muestra a continuación, puede modificar su implementación agregando un desplazamiento suave como se muestra a continuación
luego agregue el fragmento a continuación
a tus styles.css
fuente
para iphone / ios safari puedes envolver con un setTimeout
fuente
height: 100vh + 1px;
Hola chicos, esto funciona para mí en angular 4. Solo tienes que hacer referencia al padre para desplazarte en el cambio de enrutador`
layout.component.pug
layout.component.ts
fuente
@Fernando Echeverria genial! pero este código no funciona en enrutadores hash o enrutadores perezosos. porque no desencadenan cambios de ubicación. puede intentar esto:
fuente
El uso de
Router
sí mismo causará problemas que no puede superar por completo para mantener una experiencia de navegador consistente. En mi opinión, el mejor método es simplemente usar un personalizadodirective
y dejar que esto restablezca el desplazamiento al hacer clic. Lo bueno de esto es que si está en lo mismourl
que hace clic, la página también se desplazará hacia arriba. Esto es consistente con los sitios web normales. Lo básicodirective
podría verse así:Con el siguiente uso:
Esto será suficiente para la mayoría de los casos de uso, pero puedo imaginar algunos problemas que pueden surgir de esto:
universal
debido al uso dewindow
En realidad, es bastante fácil superar estos problemas:
Esto tiene en cuenta la mayoría de los casos de uso, con el mismo uso que el básico, con la ventaja de habilitarlo / deshabilitarlo:
comerciales, no leas si no quieres que te anuncien
Se podría hacer otra mejora para verificar si el navegador admite o no
passive
eventos. Esto complicará un poco más el código y es un poco oscuro si desea implementar todo esto en sus directivas / plantillas personalizadas. Es por eso que escribí una pequeña biblioteca que puede usar para abordar estos problemas. Para tener la misma funcionalidad que anteriormente, y con elpassive
evento agregado , puede cambiar su directiva a esto, si usa lang-event-options
biblioteca. La lógica está dentro delclick.pnb
oyente:fuente
Esto funcionó para mí mejor para todos los cambios de navegación, incluida la navegación hash
fuente
La idea principal detrás de este código es mantener todas las URL visitadas junto con los datos de desplazamiento respectivos en una matriz. Cada vez que un usuario abandona una página (NavigationStart), esta matriz se actualiza. Cada vez que un usuario ingresa a una nueva página (NavigationEnd), decidimos restaurar la posición Y o no dependiendo de cómo lleguemos a esta página. Si se utilizó una referencia en alguna página, nos desplazamos a 0. Si se utilizaron las funciones de retroceso / avance del navegador, nos desplazamos a Y guardado en nuestra matriz. Lo siento por mi ingles :)
fuente
window.scrollTo()
no funciona para mí en Angular 5, así que he usadodocument.body.scrollTop
como,fuente
Si está cargando diferentes componentes con la misma ruta, puede usar ViewportScroller para lograr lo mismo.
fuente
window scroll top
Tanto window.pageYOffset como document.documentElement.scrollTop devuelve el mismo resultado en todos los casos. window.pageYOffset no es compatible con IE 9.
app.component.ts
app.component.html
fuente