Ich hatte das gleiche Problem, ich benutze eine AfterViewChecked
und @ViewChild
Kombination (Angular2 Beta.3).
Die Komponente:
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) { }
}
}
Die Vorlage:
<div #scrollMe style="overflow: scroll; height: xyz;">
<div class="..."
*ngFor="..."
...>
</div>
</div>
Das ist natürlich ziemlich einfach. DasAfterViewChecked
Auslöser jedes Mal, wenn die Ansicht überprüft wurde:
Implementieren Sie diese Schnittstelle, um nach jeder Überprüfung der Ansicht Ihrer Komponente benachrichtigt zu werden.
Wenn Sie beispielsweise ein Eingabefeld zum Senden von Nachrichten haben, wird dieses Ereignis nach jeder Eingabe ausgelöst (um nur ein Beispiel zu nennen). Wenn Sie jedoch speichern, ob der Benutzer manuell gescrollt hat, und dann das überspringen scrollToBottom()
, sollte dies in Ordnung sein.
Die einfachste und beste Lösung dafür ist:
Fügen Sie diese
#scrollMe [scrollTop]="scrollMe.scrollHeight"
einfache Sache auf der Vorlagenseite hinzuHier ist der Link für WORKING DEMO (mit Dummy-Chat-App) UND FULL CODE
quelle
Expression has changed after it was checked. Previous value: 'scrollTop: 1758'. Current value: 'scrollTop: 1734'
. Hast du es gelöst?Ich habe eine Überprüfung hinzugefügt, um festzustellen, ob der Benutzer versucht hat, nach oben zu scrollen.
Ich werde das hier einfach lassen, wenn es jemand will :)
und der Code:
quelle
Die akzeptierte Antwort wird beim Scrollen durch die Nachrichten ausgelöst. Dadurch wird dies vermieden.
Sie möchten eine solche Vorlage.
Anschließend möchten Sie eine ViewChildren-Annotation verwenden, um neue Nachrichtenelemente zu abonnieren, die der Seite hinzugefügt werden.
quelle
Erwägen Sie die Verwendung
Siehe https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
quelle
Wenn Sie sicher sein möchten, dass Sie nach Abschluss von * ngFor bis zum Ende scrollen, können Sie dies verwenden.
Wichtig hier ist, dass die Variable "last" definiert, ob Sie sich gerade am letzten Element befinden, sodass Sie die Methode "scrollToBottom" auslösen können
quelle
quelle
Ich teile meine Lösung, weil ich mit dem Rest nicht ganz zufrieden war. Mein Problem dabei
AfterViewChecked
ist, dass ich manchmal nach oben scrolle und aus irgendeinem Grund dieser Life Hook aufgerufen wird und mich nach unten scrollt, selbst wenn es keine neuen Nachrichten gab. Ich habe versucht, es zu verwenden,OnChanges
aber dies war ein Problem, das mich zu dieser Lösung führte. Leider wurde nurDoCheck
mit gescrollt, bevor die Nachrichten gerendert wurden, was auch nicht nützlich war. Deshalb habe ich sie so kombiniert, dass DoCheck im Grunde angibt,AfterViewChecked
ob es aufgerufen werden sollscrollToBottom
.Freut mich über Feedback.
chat.component.html
chat.component.sass
quelle
const isScrolledDown = Math.abs(this.scrollable.nativeElement.scrollHeight - this.scrollable.nativeElement.scrollTop - this.scrollable.nativeElement.clientHeight) <= 3.0;
(wobei 3.0 Toleranz in Pixel ist). Es kann verwendet werden,ngDoCheck
um bedingt nicht zu setzenshouldScrollDown
,true
wenn der Benutzer manuell nach oben gescrollt wird.ngAfterViewChecked
mit dem anderen BooleschenshouldScrollDown
numberOfMessagesChanged
if (this.numberOfMessagesChanged && !isScrolledDown)
, aber ich denke, du hast die Absicht meines Vorschlags nicht verstanden. Meine eigentliche Absicht ist es, nicht automatisch nach unten zu scrollen, selbst wenn eine neue Nachricht hinzugefügt wird, wenn der Benutzer manuell nach oben gescrollt hat. Wenn Sie nach oben scrollen, um den Verlauf anzuzeigen, wird der Chat nach unten gescrollt, sobald eine neue Nachricht eintrifft. Dies kann sehr ärgerlich sein. :) Also, mein Vorschlag war zu überprüfen, ob der Chat nach oben gescrollt wird, bevor eine neue Nachricht zum DOM hinzugefügt wird, und nicht automatisch zu scrollen, wenn dies der Fall ist.ngAfterViewChecked
ist zu spät, weil DOM bereits geändert wurde.Die Antwort von Vivek hat bei mir funktioniert, hat jedoch dazu geführt, dass sich ein Ausdruck geändert hat, nachdem der Fehler überprüft wurde. Keiner der Kommentare hat bei mir funktioniert, aber ich habe die Strategie zur Änderungserkennung geändert.
quelle
Im Winkel mit Material Design Sidenav musste ich Folgendes verwenden:
quelle
quelle
Nachdem Sie andere Lösungen gelesen haben, ist die beste Lösung, die ich mir vorstellen kann, sodass Sie nur das ausführen, was Sie benötigen: Sie verwenden ngOnChanges, um die richtige Änderung zu erkennen
Und Sie verwenden ngAfterViewChecked, um die Änderung tatsächlich zu erzwingen, bevor sie gerendert wird, aber nachdem die volle Höhe berechnet wurde
Wenn Sie sich fragen, wie Sie scrollToBottom implementieren sollen
quelle