Tuve el mismo problema, estoy usando una combinación AfterViewChecked
y @ViewChild
(Angular2 beta.3).
El componente:
import {..., AfterViewChecked, ElementRef, ViewChild, OnInit} from 'angular2/core'
@Component({
...
})
export class ChannelComponent implements OnInit, AfterViewChecked {
@ViewChild('scrollMe') private myScrollContainer: ElementRef;
ngOnInit() {
this.scrollToBottom();
}
ngAfterViewChecked() {
this.scrollToBottom();
}
scrollToBottom(): void {
try {
this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight;
} catch(err) { }
}
}
La plantilla:
<div #scrollMe style="overflow: scroll; height: xyz;">
<div class="..."
*ngFor="..."
...>
</div>
</div>
Por supuesto, esto es bastante básico. Los AfterViewChecked
disparadores cada vez que se verificó la vista:
Implemente esta interfaz para recibir notificaciones después de cada verificación de la vista de su componente.
Si tiene un campo de entrada para enviar mensajes, por ejemplo, este evento se activa después de cada tecla (solo para dar un ejemplo). Pero si guarda si el usuario se desplazó manualmente y luego omite el scrollToBottom()
, debería estar bien.
déjame ajustar eso
fuente
La mejor y más simple solución para esto es:
Agregue esta
#scrollMe [scrollTop]="scrollMe.scrollHeight"
cosa simple en el lado de la PlantillaAquí está el enlace para la demostración de trabajo (con la aplicación de chat ficticia) Y EL CÓDIGO COMPLETO
fuente
Expression has changed after it was checked. Previous value: 'scrollTop: 1758'. Current value: 'scrollTop: 1734'
. ¿Lo resolviste?Agregué un cheque para ver si el usuario intentó desplazarse hacia arriba.
Voy a dejar esto aquí si alguien lo quiere :)
y el código:
fuente
La respuesta aceptada se dispara mientras se desplaza por los mensajes, esto evita eso.
Quieres una plantilla como esta.
Luego, desea utilizar una anotación de ViewChildren para suscribirse a los nuevos elementos de mensaje que se agregan a la página.
fuente
Considere usar
Ver https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
fuente
Si quiere estar seguro de que se desplaza hasta el final después de que * ngFor haya terminado, puede usar esto.
Importante aquí, la "última" variable define si se encuentra actualmente en el último elemento, por lo que puede activar el método "scrollToBottom"
fuente
fuente
Compartiendo mi solución, porque no estaba del todo satisfecho con el resto. Mi problema con
AfterViewChecked
es que a veces me desplazo hacia arriba y, por alguna razón, se llama a este gancho de vida y me desplaza hacia abajo incluso si no había mensajes nuevos. Intenté usar,OnChanges
pero esto fue un problema, lo que me llevó a esta solución. Desafortunadamente, al usar soloDoCheck
, se desplazaba hacia abajo antes de que se procesaran los mensajes, lo que tampoco fue útil, así que los combiné para que DoCheck básicamente indiqueAfterViewChecked
si debería llamarscrollToBottom
.Feliz de recibir comentarios.
chat.component.html
chat.component.sass
fuente
const isScrolledDown = Math.abs(this.scrollable.nativeElement.scrollHeight - this.scrollable.nativeElement.scrollTop - this.scrollable.nativeElement.clientHeight) <= 3.0;
(donde 3.0 es la tolerancia en píxeles). Puede ser utilizado enngDoCheck
condicionalmente no se estableceshouldScrollDown
atrue
si el usuario se desplaza manualmente.ngAfterViewChecked
con el otro booleano. Cambié elshouldScrollDown
nombrenumberOfMessagesChanged
para dar algo de claridad sobre a qué se refiere exactamente este booleano.if (this.numberOfMessagesChanged && !isScrolledDown)
, pero creo que no entendió la intención de mi sugerencia. Mi verdadera intención es no desplazarme hacia abajo automáticamente incluso cuando se agrega un mensaje nuevo, si el usuario se desplazó manualmente hacia arriba. Sin esto, si se desplaza hacia arriba para ver el historial, el chat se desplazará hacia abajo tan pronto como llegue un nuevo mensaje. Este puede ser un comportamiento muy molesto. :) Entonces, mi sugerencia fue verificar si el chat se desplaza hacia arriba antes de agregar un nuevo mensaje al DOM y no autodesplazarse, si es así.ngAfterViewChecked
es demasiado tarde porque DOM ya cambió.La respuesta de Vivek me funcionó, pero resultó en que una expresión cambió después de que se verificó el error. Ninguno de los comentarios me funcionó, pero lo que hice fue cambiar la estrategia de detección de cambios.
fuente
En angular usando material design sidenav tuve que usar lo siguiente:
fuente
fuente
Después de leer otras soluciones, la mejor solución en la que puedo pensar, para que ejecute solo lo que necesita es la siguiente: usa ngOnChanges para detectar el cambio adecuado
Y usa ngAfterViewChecked para hacer cumplir el cambio antes de que se procese, pero después de que se calcula la altura completa
Si se pregunta cómo implementar scrollToBottom
fuente