angular2滚动到底部(聊天风格)

在ng-for循环中有一组单元组件。 我拥有一切,但我似乎无法弄清楚

目前我有一个

setTimeout(() => { scrollToBottom(); }); 

但是这并不是一直工作,因为图像asynchronous地将视口向下推。

什么是适当的方式滚动到angular2聊天窗口的底部?

我有同样的问题,我使用AfterViewChecked@ViewChild组合(Angular2 beta.3)。

组件:

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

模板:

 <div #scrollMe style="overflow: scroll; height: xyz;"> <div class="..." *ngFor="..." ...> </div> </div> 

当然这是非常基本的。 AfterViewChecked触发器每次检查视图时:

在每次检查组件视图后,实现此接口以获得通知。

如果你有一个用于发送消息的input字段,那么在每个键入之后触发这个事件(只是举个例子)。 但是,如果你保存用户是否手动滚动,然后跳过scrollToBottom()你应该没问题。

最简单,最好的解决scheme是:

模板一侧添加这个#scrollMe [scrollTop]="scrollMe.scrollHeight"简单的东西

 <div style="overflow: scroll; height: xyz;" #scrollMe [scrollTop]="scrollMe.scrollHeight"> <div class="..." *ngFor="..." ...> </div> </div> 

这里是工作演示 (与虚拟聊天应用程序)和完整的代码的链接

将与Angular2和最多5,上面的演示在Angular5中完成。


注意 :

对于错误: ExpressionChangedAfterItHasBeenCheckedError

请检查您的CSS,这是一个CSS方面的问题,而不是Angular方面,用户@KHAN之一已经通过消除overflow:auto; height: 100%; overflow:auto; height: 100%;div 。 (请检查对话的细节)

我添加了一个检查,看看用户是否试图向上滚动。

我只是要离开这里,如果有人想要的话:)

 <div class="jumbotron"> <div class="messages-box" #scrollMe (scroll)="onScroll()"> <app-message [message]="message" [userId]="profile.userId" *ngFor="let message of messages.slice().reverse()"></app-message> </div> <textarea [(ngModel)]="newMessage" (keyup.enter)="submitMessage()"></textarea> </div> 

和代码:

 import { AfterViewChecked, ElementRef, ViewChild, Component, OnInit } from '@angular/core'; import {AuthService} from "../auth.service"; import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/switchMap'; import 'rxjs/add/operator/concatAll'; import {Observable} from 'rxjs/Rx'; import { Router, ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-messages', templateUrl: './messages.component.html', styleUrls: ['./messages.component.scss'] }) export class MessagesComponent implements OnInit { @ViewChild('scrollMe') private myScrollContainer: ElementRef; messages:Array<MessageModel> newMessage = '' id = '' conversations: Array<ConversationModel> profile: ViewMyProfileModel disableScrollDown = false constructor(private authService:AuthService, private route:ActivatedRoute, private router:Router, private conversationsApi:ConversationsApi) { } ngOnInit() { } public submitMessage() { } ngAfterViewChecked() { this.scrollToBottom(); } private onScroll() { let element = this.myScrollContainer.nativeElement let atBottom = element.scrollHeight - element.scrollTop === element.clientHeight if (this.disableScrollDown && atBottom) { this.disableScrollDown = false } else { this.disableScrollDown = true } } private scrollToBottom(): void { if (this.disableScrollDown) { return } try { this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight; } catch(err) { } } } 

这些答案都没有一半是正派的。 滚动浏览消息时接受的答案会被触发。

你想要一个这样的模板。

 <div #content> <div #messages *ngFor="let message of messages"> {{message}} </div> </div> 

然后,您要使用ViewChildren注释来订阅添加到页面的新消息元素。

 @ViewChildren('messages') messages: QueryList<any>; @ViewChild('content') content: ElementRef; ngAfterViewInit() { this.messages.changes.subscribe(this.scrollToBottom); } scrollToBottom = () => { try { this.content.nativeElement.scrollTop = this.content.nativeElement.scrollHeight; } catch (err) {} } 

在angular度使用材料devisesidenav我不得不使用以下内容:

 let ele = document.getElementsByClassName('md-sidenav-content'); let eleArray = <Element[]>Array.prototype.slice.call(ele); eleArray.map( val => { val.scrollTop = val.scrollHeight; });