【问题标题】:Angular 2. How to understand that Angular finished rendering after input data had changed?Angular 2. 如何理解 Angular 在输入数据发生变化后完成渲染?
【发布时间】:2016-12-23 04:48:28
【问题描述】:

我有一个组件,我们称之为UserComponent。该组件包含用于显示数据的网格组件。每行的单元格中都有按钮,删除、编辑、图表等。这是该组件的简化 html 模板:

<div>
   ...grid component goes here
   ... and other stuff
   <app-edit-user-graph [user]="selectedUser" [department]="department" [organization]="organization"></app-edit-user-graph>
</div>

当用户点击单元格内的Graph 按钮时,我会处理它: this.selectedUser = this.tableApi.row($tr).data(); 而且,如您所见,selecedUser 被传递给另一个组件,即app-edit-user-graph

这个组件是模态窗口,有很多选择组件和其他控件。这是其模板的一部分:

<th *ngFor="let name of heads">
   <div>
      <span>{{name}}</span>
      <span>
      <ng-select [items]="userProjects" 
         [allowClear]="true"
         (data)="update($event, name)"          
         [active]="setActive(name)">
      </ng-select>
      </span>
   </div>
</th> 

我监听app-edit-user-graph 组件的变化:

@ViewChildren(SelectComponent)
selects: SelectComponent[];

@Input() user: User;
... other inputs

ngOnChanges(changes) {
   if (!changes.user || (changes.user && !changes.user.currentValue.id)) {
      return;
   }

   this.userService.getUserProjects(this.user.id).subscribe(p=> {
      this.userProjects = p;
      this.updateSelects();
   } 

} 

public updateSelects() {
    let rowSelects = this.selects;
    let selectedValues = this.getSelectedValue(rowSelects);
    let availableValues = this.getAvailableValues(selectedValues, this.userProjects);

    rowSelects.forEach(s => {
            s.items = availableValues;
    })
}

方法this.updateSelects 获取所有选择组件并过滤一些值。 问题如下。当我第一次单击时,updateSelects 方法中的selects 为空。我明白为什么,因为 Angular 还没有完成渲染选择。当我再次打开模式时,对于其他记录,我会得到上一组选择。

那么,问题来了,如何理解 Angular 在输入数据发生变化后完成渲染?

【问题讨论】:

  • 你能做一个Plunker 的例子吗?
  • @adriancarriger 这将非常困难,因为网格和其他 3-rd 方组件。

标签: angular


【解决方案1】:

此代码设置userProjects 并立即调用updateSelects()

  this.userProjects = p;
  this.updateSelects();

Angular 没有机会在两者之间做任何事情。 通过显式调用更改检测,您可以指示 Angular 更新 DOM:

constructor(private cdRef:ChangeDetectorRef) {}

ngOnChanges(changes) {
   if (!changes.user || (changes.user && !changes.user.currentValue.id)) {
      return;
   }

   this.userService.getUserProjects(this.user.id).subscribe(p=> {
      this.userProjects = p;
      this.cdRef.detectChanges(); // <<== enforce change detection
      this.updateSelects();
   } 
}

【讨论】:

  • 是的,我明白这个问题。在我更新元素时​​,Angular 尚未完成更新 dom。因此,我得到了旧的选择。我已经尝试了您的建议,但没有看到任何变化。 detectChanges 是否异步运行?我需要事件或其他东西来了解 Angular 何时更新了我的 dom,我可以使用我的 updateSelects
  • detectChanges() 运行同步。从您的问题中不清楚rowSelects 是什么。
  • 这是SelectComponent的数组。 SelectComponent 是 ng-select 库
  • 您必须使用 detectChanges 来更改该数组。因为您问题中的代码没有显示这部分,所以我不知道如何帮助您。
  • 问题中的所有代码。在模板中你可以看到ng-select 标签。在组件中,我通过@ViewChildren(SelectComponent) selects: SelectComponent[]; 获得所有选择。
猜你喜欢
  • 2017-11-25
  • 2018-12-20
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
  • 2017-08-08
  • 2017-01-21
  • 2021-09-11
  • 2018-11-17
相关资源
最近更新 更多