2016-06-16 7 views
4

私は角度2でComponentContainerを実装しようとしています。たとえば、AndroidのLinearLayoutに似た、他のコンポーネントを動的に追加できます。角2はコンテナにコンポーネントのインスタンスを動的に追加します

これまでのところ、 Angular 2 dynamic tabs with user-click chosen components を使用して、タイプを渡すコンポーネントを動的に追加できます。

私の問題は、このメソッドを使用すると、作成されたコンポーネントがそのタイプによってのみ作成され、引数を与える方法がわかりません。

これは私が何をやったかである:私は動的にChildComponentsを追加することができます

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, AfterViewInit, 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, Type, 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); 
    } 
} 

をどのようにテキストを設定できますか?

EDIT:

私は他の人に役立つことができれば知っているが、ChildComponentの引数クラスを定義し、特定の引数を含むオブジェクトの配列としてContainerComponentの要素の配列を更新していません、私は簡単にChildComponentsに特定の引数を渡すことができます。

container.component.ts

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

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

@Component({ 
    selector: 'wrapper-component', 
    template: '<div #container></div>' 
}) 
class WrapperComponent implements OnChanges, AfterViewInit, 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, Type, 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); 
    } 
} 

答えて

5

あなたは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参照してください。

+1

ありがとうございます。 – pasianos

関連する問題