ng4 componentFactory将它放在DOM目标中

Nrz*_*ine 5 factory angular-components angular

我想做什么

我正在制作一个投票系统,它将在网站周围的多个组件中重复使用.为了保持其干燥,我想从任何组件创建投票组件,到指定的DOM元素..组件已被创建后,实例变量必须设置(在这种情况下model:stringpk:number,公共).

预期结果

我希望组件在指定位置呈现,打印在工厂创建组件后立即设置的正确数据.投票底部的输出应该是Model: project PK: 1

实际情况

ComponentFactory目前有两个由Component工厂创建的投票组件的输出:

  1. 在正确的位置(目标div),但没有设置实例变量. 此搜索

  2. 在页面的底部,但这是另一个问题,在以后的时间和其他主题.

一些代码

@NgModule({
    ..
    declarations: [
        AppComponent,
        ProjectComponent, // parent for voteContainer
        VoteComponent, // Dynamic component
    ],
    entryComponents: [
        VoteComponent,
    ], ..
})
Run Code Online (Sandbox Code Playgroud)

包含VoteComponent工厂的父组件

export class ProjectDetailComponent implements AfterViewInit {
    @ViewChild('voteComponentContainer', {read: ViewContainerRef}) voteComponentContainer;

    public ngAfterViewInit() {
        this.factoryVoteComponent();
    }

    private factoryVoteComponent() {
        const voteComponentFactory = this.componentFactoryResolver.resolveComponentFactory(VoteComponent);
        const voteComponentRef = this.viewContainerRef.createComponent(voteComponentFactory);
        voteComponentRef.instance.model = "project";
        voteComponentRef.instance.pk = 1;
        voteComponentRef.changeDetectorRef.detectChanges();
    }
}
Run Code Online (Sandbox Code Playgroud)

动态组件目标:

<vote-component-container></vote-component-container>
Run Code Online (Sandbox Code Playgroud)

基本投票组件

@Component({
    selector: 'vote-component-container',
    templateUrl: 'vote.component.html',
})

export class VoteComponent {
    public model:string;
    public pk:number;
    public constructor(){}
}
Run Code Online (Sandbox Code Playgroud)

我试过了什么

我一直在努力解决这个问题已经有一段时间了,所以有很多尝试让它发挥作用.最后的尝试是为工厂创建ViewChild.

除此之外,我一直在玩名称,设置组件模板接收器的不同方法等.

我想问的是什么

对于我现在正在尝试的情况,有没有人对动态组件的使用有任何经验?我希望在正确的方向上推动如何解决在正确的位置呈现的组件的问题,但没有可用的属性.

Nrz*_*ine 0

经过更多的研究、测试失败并尝试更多 - 我找到了一个解决方案。我还不是 100% 满意,因为它变得不那么干燥和有条理——但现在:

首先,我必须调整将数据传递到动态生成的组件的方式。我必须更新我的选择器目标以接受所需的属性。就我而言,modelobjectId.

<vote-component-container [model]="'project'" [objectId]="projectId"></vote-component-container>
Run Code Online (Sandbox Code Playgroud)

要将此数据链接到VoteComponent,其VoteComponent本身需要@Input这些数据输入的设置器,例如:

import { Input, Component, AfterViewInit } from '@angular/core';

@Component({
    selector: 'vote-component-container',
    templateUrl: 'vote.component.html',
})

export class VoteComponent implements AfterViewInit {
    // Temp public for testing
    public _objectId:number;
    public _model:string;

    public constructor(){}
    public ngAfterViewInit(){
        this.getVotes();
    }

    @Input('objectId')
    set objectId(objectId:number){
        this._objectId = objectId;
    }

    @Input('model')
    set model(model:string){
        this._model = model;
    }

    public getVotes(){
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

最终在我的父组件中,我期望 params['id'] 部分是在 ngAfterInit 中调用该函数时。但事实并非如此,所以我不得不等待承诺。

@ViewChild('voteComponentContainer', {read: ViewContainerRef}) target: ViewContainerRef;
private factoryVoteComponent(){
    this.activatedRoute.params.subscribe((params: Params) => {
        this.model = 'project';
        this.projectId = params['id'];

        let voteComponentFactory = this.componentFactoryResolver.resolveComponentFactory(VoteComponent);
        this.voteComponentRef = this.viewContainerRef.createComponent(voteComponentFactory);
        this.voteComponentRef.changeDetectorRef.detectChanges();
    });
}
Run Code Online (Sandbox Code Playgroud)