40

I am able to load a dynamic Angular 2 component using ComponentResolver and ViewContainerRef.

However I am not able to figure out how to pass any input variable of child component into this.

parent.ts

    @Component({
     selector: "parent",
     template: "<div #childContainer ></div>"
    })
    export class ParentComponent {
      @ViewChild("childContainer", { read: ViewContainerRef }) childContainer: ViewContainerRef;

      constructor(private viewContainer: ViewContainerRef, private _cr: ComponentResolver) {}

      loadChild = (): void => {
           this._cr.resolveComponent(Child1Component).then(cmpFactory => {               
              this.childContainer.createComponent(cmpFactory);
           });
      }
    }

child1

 @Component({
   selector: "child1",
   template: "<div>{{var1}}</div><button (click)='closeMenu()'>Close</button>"
 })
 export class Child1Component {
    @Input() var1: string;
    @Output() close: EventEmitter<any> = new EventEmitter<any>();

    constructor() {}

    closeMenu = (): void => {
      this.close.emit("");
    }
 }

so in above example say loadChild is being called on a button click, I am able to load Child1Component, but how to pass var1 Input of child? Also How to subscribe to close EventEmitter decorated with @Output

2 Answers 2

64

You have to pass it imperatively like:

loadChild(): void {
  this._cr.resolveComponent(Child1Component).then(cmpFactory => {               
    let cmpRef = this.childContainer.createComponent(cmpFactory);
     cmpRef.instance.var1 = someValue;  
   });
 }

also similar with registering handlers for outputs.

loadChild(): void {
  this._cr.resolveComponent(Child1Component).then(cmpFactory => {                
    let instance: any = this.childContainer.createComponent(cmpFactory).instance;
    if (!!instance.close) {
      // close is eventemitter decorated with @output 
      instance.close.subscribe(this.close);
    }
  });
}

close = (): void => {
  // do cleanup stuff..
  this.childContainer.clear();
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for this, I am not getting a callback however I am getting instance directly on createComponent, Can you please update the solution and also how to use @Output function?
@Gunter, tried the same way suggested by you, but getting some exceptions in browser console and it is not working as expected. can you please help by responding to this post? stackoverflow.com/questions/38360904/…
@GünterZöchbauer: How to update data of input? Should i create a new question?
Do you know why it only works with the fat arrow function on close()? Regular annonymous doesnt work
@L1ghtk3ira because otherwise this points to where the callback is called from instead of our component class. See also developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… (you can also use .bind(this) for the same effect, but I find the arrow function syntax easier to read.
7

This is how I did it with Angular 2.2.3

let nodeElement = document.getElementById("test");
let compFactory = this.componentFactoryResolver.resolveComponentFactory(AnyCustomComponent);
let component = compFactory.create(this.viewContainerRef.injector, null, nodeElement);
// This is where you pass the @Input
component.instance.anyInput = anyInput;

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.