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