角度:无法向下滚动到元素

时间:2018-11-02 18:19:32

标签: javascript angular

我一直在推迟解决我已经有一段时间的错误了。我有下面的聊天窗口:

enter image description here

显示消息的窗口是一个单独的组件(chat-window.component.ts)。我想使用ngOnChanges滚动到底部。

当我们从父组件接收到带有消息的会话(通过异步请求从服务器接收到该消息)时,我们想滚动到window元素的底部。我们通过在ngOnChanges生命周期挂钩中调用该类的this.scrollToBottom()方法来实现。

This.scrollToBottom确实会被调用,但不会滚动到该元素的底部。有人可以看到原因吗?

聊天窗口.component.ts:在ngOnchanges中,我们在调用this.scrollToBottom()

之前会做一些同步处理
export class ChatboxWindowComponent implements OnChanges, OnInit, AfterViewChecked {

  @Input('conversation') conversation;
  @ViewChild('window') window;

  constructor() { }

  ngOnChanges() {
    // If the date separators have already been added once, we avoid doing it a second time
    const existingDateObj = this.conversation.messages.findIndex((item, i) => item.dateObj);

    if (existingDateObj === -1) {
      this.conversation.messages.forEach( (item, index, array) => {
        if (index !== 0) {
          const date1 = new Date(array[index - 1].date);
          const date2 = new Date(item.date);

          if (date2.getDate() !== date1.getDate() || date2.getMonth() !== date1.getMonth()) {
            this.conversation.messages.splice(index, 0, {date: date2, dateObj: true});
            console.log(this.conversation.messages.length);
          }
        }
      });
    }

    this.scrollToBottom();
  }

  ngOnInit() {
  }

  ngAfterViewChecked() {
  }

  isItMyMsg(msg) {
    return msg.from._id === this.conversation.otherUser.userId;
  }

  scrollToBottom() {
    try {
      console.log('scrollToBottom called');
      this.window.nativeElement.top = this.window.nativeElement.scrollHeight;
    } catch (err) {}
  }
}

聊天窗口.component.html

<div #window class="window">
  <ng-container *ngFor="let message of conversation.messages">
    <div class="date-container" *ngIf="!message.msg; else windowMsg">
      <p class="date">{{message.date | amDateFormat:'LL'}}</p>
    </div>
    <ng-template #windowMsg>
      <p
        class="window__message"
        [ngClass]="{
    'window__message--left': isItMyMsg(message),
    'window__message--right': !isItMyMsg(message)
    }"
      >
        {{message.msg}}
      </p>
    </ng-template>
  </ng-container>
</div>

2 个答案:

答案 0 :(得分:4)

滚动不起作用,因为调用scrollToBottom时尚未呈现消息列表。为了在消息显示后立即滚动,请在消息容器上设置template reference variable(例如#messageContainer

<ng-container #messageContainer *ngFor="let message of conversation.messages">
  ...
</ng-container>

然后,在代码中,您可以使用ViewChildren访问这些元素,并在触发QueryList.changes事件时滚动窗口:

@ViewChildren("messageContainer") messageContainers: QueryList<ElementRef>;

ngAfterViewInit() {
  this.scrollToBottom(); // For messsages already present
  this.messageContainers.changes.subscribe((list: QueryList<ElementRef>) => {
    this.scrollToBottom(); // For messages added later
  });
}

答案 1 :(得分:0)

您可以将以下代码添加到您的 HTML 元素中。

#window [scrollTop]="window.scrollHeight" *ngIf="messages.length > 0"

根据您的代码示例的完整代码如下,

<div #window [scrollTop]="window.scrollHeight" *ngIf="messages.length > 0" class="window">
  <ng-container *ngFor="let message of conversation.messages">
    <div class="date-container" *ngIf="!message.msg; else windowMsg">
      <p class="date">{{message.date | amDateFormat:'LL'}}</p>
    </div>
    <ng-template #windowMsg>
      <p
        class="window__message"
        [ngClass]="{
    'window__message--left': isItMyMsg(message),
    'window__message--right': !isItMyMsg(message)
    }"
      >
        {{message.msg}}
      </p>
    </ng-template>
  </ng-container>
</div>

这对我有用。 (目前,我使用的是 Angular 11)??