J'ai eu le même problème, j'utilise une combinaison AfterViewChecked
et @ViewChild
(Angular2 beta.3).
Le composant:
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) { }
}
}
Le gabarit:
<div #scrollMe style="overflow: scroll; height: xyz;">
<div class="..."
*ngFor="..."
...>
</div>
</div>
Bien sûr, c'est assez basique. Les AfterViewChecked
déclencheurs à chaque fois que la vue a été vérifiée:
Implémentez cette interface pour être notifié après chaque vérification de la vue de votre composant.
Si vous avez un champ d'entrée pour l'envoi de messages par exemple, cet événement est déclenché après chaque keyup (juste pour donner un exemple). Mais si vous enregistrez si l'utilisateur a fait défiler manuellement et ensuite ignorer, tout scrollToBottom()
devrait être bien.
laissez-moi corriger cela
la source
La solution la plus simple et la meilleure pour cela est:
Ajoutez cette
#scrollMe [scrollTop]="scrollMe.scrollHeight"
chose simple du côté du modèleVoici le lien pour WORKING DEMO (avec application de chat factice) ET CODE COMPLET
la source
Expression has changed after it was checked. Previous value: 'scrollTop: 1758'. Current value: 'scrollTop: 1734'
. L'avez-vous résolu?J'ai ajouté une vérification pour voir si l'utilisateur a essayé de faire défiler vers le haut.
Je vais juste laisser ça ici si quelqu'un le veut :)
et le code:
la source
La réponse acceptée se déclenche lors du défilement des messages, cela évite cela.
Vous voulez un modèle comme celui-ci.
Ensuite, vous souhaitez utiliser une annotation ViewChildren pour vous abonner aux nouveaux éléments de message ajoutés à la page.
la source
Pensez à utiliser
Voir https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
la source
Si vous voulez être sûr que vous faites défiler jusqu'à la fin une fois que * ngFor est terminé, vous pouvez utiliser ceci.
Important ici, la variable "last" définit si vous êtes actuellement au dernier élément, vous pouvez donc déclencher la méthode "scrollToBottom"
la source
la source
Partage de ma solution, car je n'étais pas complètement satisfait du reste. Mon problème avec
AfterViewChecked
c'est que parfois je défile vers le haut, et pour une raison quelconque, ce hook de vie est appelé et il me fait défiler même s'il n'y avait pas de nouveaux messages. J'ai essayé d' utiliser ,OnChanges
mais c'était un problème, ce qui me conduit à cette solution. Malheureusement, en utilisant uniquement , il faisait défiler vers le bas avant que les messages ne soient rendus, ce qui n'était pas utile non plus, alors je les ai combinés pour que DoCheck indique essentiellement s'il doit appeler .DoCheck
AfterViewChecked
scrollToBottom
Heureux de recevoir des commentaires.
chat.component.html
chat.component.sass
la source
const isScrolledDown = Math.abs(this.scrollable.nativeElement.scrollHeight - this.scrollable.nativeElement.scrollTop - this.scrollable.nativeElement.clientHeight) <= 3.0;
(où 3.0 est la tolérance en pixels). Il peut être utiliséngDoCheck
pour ne pas être définishouldScrollDown
de manièretrue
conditionnelle si l'utilisateur fait défiler manuellement vers le haut.ngAfterViewChecked
avec l'autre booléen. J'ai changé deshouldScrollDown
nomnumberOfMessagesChanged
pour donner un peu de clarté sur ce à quoi exactement ce booléen se réfère.if (this.numberOfMessagesChanged && !isScrolledDown)
, mais je pense que vous n'avez pas compris l'intention de ma suggestion. Mon intention réelle est de ne pas faire défiler automatiquement vers le bas même lorsqu'un nouveau message est ajouté, si l'utilisateur a fait défiler manuellement vers le haut. Sans cela, si vous faites défiler vers le haut pour voir l'historique, le chat défilera vers le bas dès l'arrivée d'un nouveau message. Cela peut être un comportement très ennuyeux. :) Donc, ma suggestion était de vérifier si le chat défile vers le haut avant qu'un nouveau message ne soit ajouté au DOM et de ne pas faire défiler automatiquement, si c'est le cas.ngAfterViewChecked
est trop tard car DOM a déjà changé.La réponse de Vivek a fonctionné pour moi, mais a abouti à une expression a changé après avoir vérifié l'erreur. Aucun des commentaires n'a fonctionné pour moi, mais j'ai changé la stratégie de détection des changements.
la source
Dans angular using material design sidenav, j'ai dû utiliser ce qui suit:
la source
la source
Après avoir lu d'autres solutions, la meilleure solution à laquelle je puisse penser, donc vous n'exécutez que ce dont vous avez besoin est la suivante: Vous utilisez ngOnChanges pour détecter le changement approprié
Et vous utilisez ngAfterViewChecked pour appliquer réellement la modification avant son rendu, mais après le calcul de la hauteur totale
Si vous vous demandez comment implémenter scrollToBottom
la source