This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

Set Properties on Dynamically Created Angular 2 Components

1:47 Angular 2 lesson by

When you generate Angular 2 components, you’re still able to access the component instance to set properties and invoke methods from the component class.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

When you generate Angular 2 components, you’re still able to access the component instance to set properties and invoke methods from the component class.

Avatar
St Clair

Hi,
I have a detachRow() method on the dynamically created component that detaches a newly created sibling of the container. Now, when button is clicked the detachRow() is invoked. I receive the row created by an @Input as you described, but the #container is part of the parent. So I will have to send an event that the parent can intercept with the index of the container to delete the appropriate component.

Now, the parent itself is instantiated by the router by a button. In this scenario, how can I communicate with the router-instantiated parent from the dynamically created child to send the row index of the dynamically created child so the parent can then use the index to delete the appropriate siblings from the container.

Hope this is clear. And thanks.

With each of these widgets that we have created, they are all WidgetThree. Right now, they're blank in here. Let's set a default value for that input.

We'll do that by creating an @Input. This is component input, don't confuse it with an HTML input, meaning that we can pass in a message. Typically, in a template, you would have my-component, and then pass in something through message like this and a string of some message.

widgets/widget-three.component.ts

@Component({
  selector: 'widget-three',
  template: `
<input #input type="text">
`
})
export class WidgetThree{
  @ViewChild('input') input;

  @Input() message

  constructor(private renderer:Renderer){}

  ngAfterViewInit(){ ... }
}

But since we're going to create these programmatically, and I'll start with a default value of, say, default value. When I set value to the message, each of these will have default value in the input.

widgets/widget-three.component.ts

@Component({
  selector: 'widget-three',
  template: `
<input #input type="text" [value]="message">
`
})
export class WidgetThree{
  @ViewChild('input') input;

  @Input() message = "default value!"

  constructor(private renderer:Renderer){}

  ngAfterViewInit(){ ... }
}

I want to be able to change that programmatically from the component that creates it. In the home component, I could actually get a reference to this widget that's created. I'll say widgetRef. Let's format this a little bit, so you can read it. Then on the widgetRef, you can get an instance of the component that that reference is referencing.

home/home.component.ts

ngAfterViewInit(){
  const widgetFactory = this.resolver.resolveComponentFactory(WidgetThree);

  this.container.createComponent(widgetFactory);
  this.container.createComponent(widgetFactory);
  this.container.createComponent(widgetFactory);
  ...
  const widgetRef = this.container
    .createComponent(widgetFactory);

  widgetRef.instance.message = "I'm last!";
}

On that instance, you can set things like the message. I'll say, I'm last.

Set instance properties

From this reference that we're getting by creating the component, you just say widgetRef.instance and, on that instance, then you can start setting the properties, the inputs, or anything that's on that component just as if you're accessing an instance of this class here. Then those values we passed in to the template as they would normally as the message is here.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?