Angular的ViewChildren无法立即看到ngFor中的所有子元素

6
我在使用ngFor生成子组件时,@ViewChildren的行为异常。 @ViewChildren查询在相当长的时间内无法看到数组中的元素。我的所有代码都在Plunker中 - 打开控制台查看。
这是我的主要组件:
@Component({
    selector: 'my-app',
    template: `
        <button (click)="addInternalComponent()">Add internal component</button>
        <app-internal #internals *ngFor="let i of indexes" [index]="i
(afterViewInit)="onAfterViewInit()"></app-internal>
    `,
})
export class App {
    @ViewChildren('internals') internals: QueryList<InternalComponent>;
    indexes = [];
    addInternalComponent() {
        console.log('adding internal component!');
        this.indexes.push(this.indexes.length);
        console.log('Not complete list', this.internals._results);

    }

    onAfterViewInit() {
        console.log('onAfterViewInit - still not complete list', this.internals._results);
    }
}

这是一个包含一些子组件的组件,我们可以通过单击按钮来添加子组件。

在将元素添加到索引数组后,生成所有子组件的ngFor循环中 - 我们没有刚刚添加的那个组件。

我可以理解这种行为 - 因为也许子组件需要一些时间来创建,并且引擎决定在创建完整的子组件之前进行控制台日志记录。

然而,我在子组件中创建了一个发射器,用于通知已经初始化了子视图和模型。但是…在父组件中处理此事件时 - 我们仍然不知道如何获取此项。这怎么可能呢?

子组件:

export class InternalComponent implements AfterViewInit {
  @Input()
  index;
  @Output()
  afterViewInit: EventEmitter<any> = new EventEmitter<any>();

  ngAfterViewInit() {
    this.afterViewInit.emit();
  }

}
1个回答

7

通知 QueryList 内容已更改的标准方法是在 ngAfterViewInit 中订阅其 changes 事件:

@ViewChildren("internals") internals: QueryList<InternalComponent>;

ngAfterViewInit() {
  this.internals.changes.subscribe((list: QueryList<InternalComponent>) => {
    // The updated QueryList is available here (with list or with this.internals)
    this.doSomethingWithInternals(list);
    this.doSomethingWithNewInternal(list.last);
    ...
  });
}

上面的事件处理可能已经满足您的需求。如果您仍然想在InternalComponent中实现afterViewInit事件,可以将组件的引用作为事件的参数传递:

export class InternalComponent implements AfterViewInit {
  @Output() afterViewInit = new EventEmitter<InternalComponent>();

  ngAfterViewInit() {
    this.afterViewInit.emit(this);
  }

}

并在事件处理程序中检索组件:

(afterViewInit)="onAfterViewInit($event)"

onAfterViewInit(component: InternalComponent) {
    this.useNewInternalComponent(component);
    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接