加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

typescript – Angular 2动态地将组件实例添加到容器中

发布时间:2020-12-17 17:26:31 所属栏目:安全 来源:网络整理
导读:我试图在Angular 2中实现一个ComponentContainer,这样你就可以动态添加其他组件,类似于 Android中的LinearLayout. 到目前为止,使用 Angular 2 dynamic tabs with user-click chosen components 我可以动态添加传递Type的组件. 我的问题是使用这个方法,创建的
我试图在Angular 2中实现一个ComponentContainer,这样你就可以动态添加其他组件,类似于 Android中的LinearLayout.

到目前为止,使用
Angular 2 dynamic tabs with user-click chosen components
我可以动态添加传递Type的组件.

我的问题是使用这个方法,创建的Component只是由它的Type创建,我不知道如何给它提供参数.

这就是我所做的:

container.component.ts

import {
    Component,OnChanges,AfterViewInit,OnDestroy,Input,Type,ViewChild,ViewContainerRef,ComponentRef,ComponentResolver,ComponentFactory
} from '@angular/core';

@Component({
    selector: 'wrapper-component',template: '<div #container></div>'
})
class WrapperComponent implements OnChanges,OnDestroy {

    @Input() type: Type;
    @ViewChild('container',{read: ViewContainerRef}) container;

    cmpRef: ComponentRef<any>;

    private isViewInitialized: boolean = false;

    constructor(private resolver: ComponentResolver) { }

    private updateComponent() { 
        if(!this.isViewInitialized)
            return;

        if(this.cmpRef)
            this.cmpRef.destroy();

        this.resolver.resolveComponent(this.type).then((factory: ComponentFactory<any>) => {
            this.cmpRef = this.container.createComponent(factory);
        })
    }

    ngOnChanges() {
        this.updateComponent();
    }

    ngAfterViewInit() {
        this.isViewInitialized = true;
        this.updateComponent();
    }

    ngOnDestroy() {
        if(this.cmpRef)
            this.cmpRef.destroy();
    }
}

@Component({
    selector: 'container-component',template: `
        <wrapper-component 
            *ngFor="let element of elements" 
            [type]="element">
        </wrapper-component>
    `,directives: [WrapperComponent]
})
export class ContainerComponent {

    private elements: Type[] = [];    

    visibility: boolean = true;

    Add(element: Type) {
        this.elements.push(element);
    }

    AddAll(elements: Type[]) {
        elements.forEach(element => {
            this.Add(element);
        });
    }

    Clear() {
        this.elements = [];
    }
}

a1.component.ts

import { Component,ViewChild } from '@angular/core'
import { ContainerComponent } from '../../components/container.component';

@Component({
    selector: 'child-component',template: '<div>a{{text}}</div>'
})
class ChildComponent {
    text: string;
}

@Component({
    selector: 'a1step',template: `
        <button (click)="onClick()">Add</button>
        <container-component #container></container-component>
    `,directives: [ContainerComponent]
})
export class A1Step {
    @ViewChild('container') container : ContainerComponent;

    onClick() {
        this.container.Add(ChildComponent);
    }
}

在这里我可以动态添加ChildComponents,但是如何设置其文本?

编辑:

我不知道是否对其他人有用,但为ChildComponent定义一个参数类,并将ContainerComponent的elements数组更新为包含特定args的对象数组,我可以轻松地将特定参数传递给ChildComponents:

container.component.ts

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

export class ChildArgs {
    type: Type;
    args: any;
}

@Component({
    selector: 'wrapper-component',OnDestroy {

    @Input() argsElement: ChildArgs;
    @ViewChild('container',{read: ViewContainerRef}) container;

    cmpRef: ComponentRef<any>;

    private isViewInitialized: boolean = false;

    constructor(private resolver: ComponentResolver) { }

    private updateComponent() { 
        if(!this.isViewInitialized)
            return;

        if(this.cmpRef)
            this.cmpRef.destroy();

        this.resolver.resolveComponent(this.argsElement.type).then((factory: ComponentFactory<any>) => {
            this.cmpRef = this.container.createComponent(factory);
            this.cmpRef.instance.args = this.argsElement.args;
        })
    }

    ngOnChanges() {
        this.updateComponent();
    }

    ngAfterViewInit() {
        this.isViewInitialized = true;
        this.updateComponent();
    }

    ngOnDestroy() {
        if(this.cmpRef)
            this.cmpRef.destroy();
    }
}

@Component({
    selector: 'container-component',template: `
        <wrapper-component 
            *ngFor="let argsElement of argsElements" 
            [argsElement]="argsElement">
        </wrapper-component>
    `,directives: [WrapperComponent]
})
export class ContainerComponent {

    private argsElements: ChildArgs[] = [];

    AddArgsElement(argsElement: ChildArgs) {
        this.argsElements.push(argsElement);
    }
}

a1.component.ts

import { Component,ViewChild } from '@angular/core'
import { ContainerComponent,ChildArgs } from '../../components/container.component';

class ChildComponentArgs {
    text: string;
}

@Component({
    selector: 'child-component',template: '<div>a{{args.text}}</div>'
})
class ChildComponent {
    args: ChildComponentArgs;
}

class ChildComponent2Args {
    text: string;
}

@Component({
    selector: 'child-component2',template: '<div>b{{args.text}}</div>'
})
class ChildComponent2 {
    args: ChildComponent2Args;
}

@Component({
    selector: 'a1step',template: `
        <button (click)="onClick()">Add</button>
        <button (click)="onClick2()">Add2</button>
        <container-component #container></container-component>
    `,directives: [ContainerComponent]
})
export class A1Step {
    @ViewChild('container') container : ContainerComponent;

    private cnt: number = 0;
    private cnt2: number = 0;

    onClick() {
        let childComponentArgs: ChildComponentArgs = new ChildComponentArgs();
        childComponentArgs.text = "" + ++this.cnt; 

        let childArgs: ChildArgs = new ChildArgs();
        childArgs.type = ChildComponent;
        childArgs.args = childComponentArgs;

        this.container.AddArgsElement(childArgs);
    }

    onClick2() {
        let childComponentArgs: ChildComponent2Args = new ChildComponent2Args();
        childComponentArgs.text = "" + ++this.cnt2; 

        let childArgs: ChildArgs = new ChildArgs();
        childArgs.type = ChildComponent2;
        childArgs.args = childComponentArgs;

        this.container.AddArgsElement(childArgs);
    }
}

解决方法

您可以使用cmpRef.instance访问创建的组件实例:

this.resolver.resolveComponent(this.type).then((factory: ComponentFactory<any>) => {
        this.cmpRef = this.container.createComponent(factory);
        this.cmpRef.instance.text = this.someText;
    })

有关完整示例,另请参见Angular 2 dynamic tabs with user-click chosen components.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读