ng4 componentFactory将它放在DOM目标

时间:2017-08-30 14:53:43

标签: angular factory angular-components

我想做什么

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

预期结果

我希望组件在指定位置呈现,打印在工厂创建组件后立即设置的正确数据。投票底部的输出应为pk:number

实际情况

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

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

  2. 在页面底部,但这是另一个问题,稍后和其他主题。

  3. 一些代码

    Model: project PK: 1

    包含VoteComponent工厂的父组件

    @NgModule({
        ..
        declarations: [
            AppComponent,
            ProjectComponent, // parent for voteContainer
            VoteComponent, // Dynamic component
        ],
        entryComponents: [
            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();
        }
    }
    

    基本投票组件

    <vote-component-container></vote-component-container>
    

    我尝试了什么

    我现在已经挣扎了很长一段时间,所以那里 是一些尝试让它工作。最后的尝试是 为工厂创建ViewChild。

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

    我想问的是什么

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

1 个答案:

答案 0 :(得分:0)

经过一些研究,测试失败并尝试了更多 - 我发现它是一个解决方案。我不是百分之百满意,因为它变得有点干燥和有组织 - 但是现在:

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

<vote-component-container [model]="'project'" [objectId]="projectId"></vote-component-container>

要将此数据与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(){
        ...
    }
}

并最终在我的父组件中,我期望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();
    });
}