如何在动态添加的组件上使用事件发射器?

时间:2016-03-26 23:30:19

标签: angular

在Eric Martinez'从Angular 2 - Adding / Removing components on the fly回答,我想限制创建的组件数量。然后在删除组件后,我尝试将该事件发送给父组件,以便父组件知道当前创建的组件数量。

在这个Plunker中,我将组件数量限制为4,然后我尝试发出一个事件来降低该数量。该事件不会发出。如何从动态添加的组件中发出事件?

// dynamic component
@Component({
    selector : 'dynamic',
    template : `
    <div>
        Component number {{_idx}} <button (click)="remove()">Remove</button>
    </div>`
})
class DynamicCmp {
    _ref: ComponentRef;
    _idx: number;
    @Output lowerIndex = new EventEmitter<any>();
    remove() {
        this._ref.dispose();
        this.lowerIndex.emit(true);
    }
}

// Parent container component    
@Component({
    selector: 'my-app',
    template : `
        <button (click)="add()">Add new component</button>
        <div #location (lowerIndex)="lowerIndex();"></div>
    `
})
export class App {
    idx: number = 0;
    constructor(private _dcl: DynamicComponentLoader, private _e: ElementRef) {}

    lowerIndex() {
        this.idx--;
        console.log("subtracted");
    }

    add() {
        if (this.idx < 4) {
            this._dcl.loadIntoLocation(DynamicCmp, this._e, 'location').then((ref) => {
            ref.instance._ref = ref;
            ref.instance._idx = this.idx++;
            });

            console.log("added")
        }
    }
}

我在这里发布了组件,因为stackoverflow需要使用plunker链接发布代码。代码与plunker

中的代码完全相同

1 个答案:

答案 0 :(得分:23)

这里的问题是动态加载的组件与它们被加载的组件没有父/子关系。这就是为什么要从动态加载的组件访问属性,你必须使用ref.instance.property。该组件未与父组件一起编译,因此父组件对 foster 组件一无所知。

现在,正如所说的那样,你可以做的是创建一个你可以订阅的属性和I wouldn't use an EventEmitter

我的解决方案是使用主题(就像我在自己的一个小项目中所做的那样)。

您的动态组件将如下所示

class DynamicCmp {

    // Subject instead of an EventEmitter
    lowerIndex: Subject<boolean> = new Subject();

    remove() {
        // We send true, although in the example is not being used
        this.lowerIndex.next(true);

        // Remove the component from the view
        this._ref.dispose();
    }
}

您正在加载动态组件的组件

template : '<div #location></div>'; // Note that I removed (lowerIndex)="..."
this._dcl.loadIntoLocation(DynamicCmp, this._e, 'location').then((ref) => {
    //...

    // Subscribe to the Subject property
    ref.instance.lowerIndex.subscribe(v => {
        this.idx--;
        console.log("subtracted");
    });
});

这是你的plnkr工作并更新到beta.12。