QueryList 未使用动态组件更新

Say*_*tan 6 angular

我有一个父组件,它可以有同一个子组件的多个实例。这里棘手的部分是子组件的实例在初始化时可用,并且基于子组件中的某些逻辑,我使用输出事件发射器从父组件重新生成另一个子组件。但是,在保存时,我只看到了放在 html 模板中的子组件的第一个实例,而不是动态生成的。我确实看到了其他类似的问题,但似乎没有人遇到同样的问题。我在这里缺少什么?

任何帮助将不胜感激。

更新 - 开始

如果有人想玩弄并找到原因,添加了一个plunker来演示问题

https://plnkr.co/edit/FW49ztzsg5uyXF7DtHDY?p=preview

更新 - 结束

父组件

import { Component, OnInit, ViewContainerRef, ViewChild, ComponentFactoryResolver, ViewChildren, QueryList } from '@angular/core';
import { ChildComponent } from './child/child.component';

@Component( {
    selector: 'parent-cmp',
    entryComponents: [ChildComponent],
    template: `
        <child-cmp (onSomeSelectionChange)="onSomeSelectionChange($event)"></child-cmp>
        <div #childCompSection></div>
        <button (click)="save()">Save</button>
    `
} )
export class ParentComponent implements OnInit {

    @ViewChild( 'childCompSection', { read: ViewContainerRef } ) childCompSection: any;
    currentComponentHolder: any;
    @ViewChildren( ChildComponent ) childComponents: QueryList<ChildComponent>;

    constructor( private resolver: ComponentFactoryResolver ) { }

    ngOnInit() {
        // do some stuff to load initial view, nothing done using childComponents
    }

    onSomeSelectionChange( someValue ) {
        if ( someValue !== 3 ) {
            let componentFactory = this.resolver.resolveComponentFactory( ChildComponent );
            this.currentComponentHolder = this.childCompSection.createComponent( componentFactory );
            this.currentComponentHolder.instance.onSomeSelectionChange.subscribe( data => this.onSomeSelectionChange( data ) );
        }
    }

    // Need all child components (which includes dynamically generated components) here 
    save() {
        console.log(this.childComponents); // This just prints the child-cmp object that is already added not the ones that are dynamically added via ComponentFactoryResolver
    }

}
Run Code Online (Sandbox Code Playgroud)

子组件

import { Component, Output, EventEmitter } from '@angular/core';
import { ChildComponent } from './child/child.component';

@Component( {
    selector: 'child-cmp',
    template: `
        <div>
            <select [(ngModel)]="selectedValue" (ngModelChange)="showNumberField($event)">
                <option value="0">Select...</option>
                <option value="1">Add...</option>
                <option value="2">Subtract...</option>
                <option selected value="3">End</option>
            </select>
            <div *ngIf="showField">
                <label>Number:</label><input type="number" [(ngModel)]="numValue">
            </div>
        </div>
    `
} )
export class ChildComponent {

    @Output() onSomeSelectionChange = new EventEmitter<Lookup>();
    selectedValue: number;
    numValue: number;
    showField: boolean = false;

    showNumberField(value) {
        if(value !== 3) {
            showField = true;
        }
        this.onSomeSelectionChange.emit( value ); // This does work fine and another instance of the child component is generated from parent component but QueryList in parent component does not get updated
    }
}
Run Code Online (Sandbox Code Playgroud)

Joe*_*ene 8

我遇到了同样的问题,发现您可以订阅查询列表更改,如果添加或删除元素,则会触发该更改。希望能帮助其他人...

@ViewChildren(MyComponent) myComp: QueryList<MyComponent>;

ngAfterViewInit() {
    this.myComp.changes
            .subscribe((queryChanges) => {
                // Do something
            });
}
Run Code Online (Sandbox Code Playgroud)


Say*_*tan 5

从Angular 聊天论坛得到确认,@ViewChildren/@ViewChild 只能读取视图中已有的元素。由于动态组件在视图初始化期间不可用,因此我必须维护所有此类动态生成的组件的列表以跟踪它们。