5

I'm trying to build a component that appends another component dynamically. As an example here is my parent class:

import { Component, ComponentRef, ViewChild, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';

@Component({
    templateUrl: './app/sample-component.component.html',
    selector: 'sample-component'
})
export class SampleComponent {

    @ViewChild('dynamicContent', { read: ViewContainerRef })
    protected dynamicComponentTarget: ViewContainerRef;
    private currentComponent: ComponentRef<any>;
    private selectedValue: any;

    constructor(private componentResolver: ComponentFactoryResolver) {

    }

    private appendComponent(componentType: any) {
        var factory = this.componentResolver.resolveComponentFactory(componentType);
        this.currentComponent = this.dynamicComponentTarget.createComponent(factory);
    }
}

sample-component.component.html:

<div #dynamicContent></div>

It works fine with appending an element, but i have no idea about how to bind two-way dynamically, like i do in static components: [(ngModel)]="selectedValue"

2 Answers 2

9

Binding with dynamically added components is not supported.

You can use a shared service to communicate with dynamically added components (https://angular.io/docs/ts/latest/cookbook/component-communication.html)
or you can read/set imperatively using the this.currentComponent reference:

private appendComponent(componentType: any) {
    var factory = this.componentResolver.resolveComponentFactory(componentType);
    this.currentComponent = this.dynamicComponentTarget.createComponent(factory);
    this.currentComponent.instance.value = this.selectedValue;
    this.currentComponent.instance.valueChange.subscribe(val => this.selectedValue = val);
}
Sign up to request clarification or add additional context in comments.

4 Comments

Ok, then I think it's better to use ControlValueAccessor interface, but i'm not sure if any component, that provides construction like [(ngModel)]="selectedValue" inmplements this interface. So the it can be used this way this.currentComponent.instance.registerOnChange(this.valueChangeHandler);
Not sure what you mean. ControlValueAccessor implementation is required for [(ngModel)]="..." to work, but that's also an Angular2 binding and therefore not supported on dynamically added components.
could you please expand on this @GünterZöchbauer ? How does this.currentComponent.instance.value associate with the DOM input element inside of componentTypes template: ` ... ` in order to replace <input type="text" [(ngModel)]="selectedValue"> ? I would be most grateful if you could share a plunker.
@BenjaminMcFerren it would need to be something like <input [(ngModel)]="value" ...> I think you then need to invoke change detection manually. Either using this.currentInstance... (don't remember details) or inject this.cdRef:ChangeDetectorRef to the dynamically added component and call this.currentComponent.instance.cdRef.detectChanges()
0

This is a workaround.

from the code posted above.

private appendComponent(componentType: any) {
 var factory = this.componentResolver.resolveComponentFactory(componentType);
 this.currentComponent = this.dynamicComponentTarget.createComponent(factory);
 this.currentComponent.instance.value = this.selectedValue;
 this.currentComponent.instance.valueChange.subscribe(val => this.selectedValue = val);

}

Make dynamic variable as a Object and now assign it to the variable in parent component.

//at dynamically created component
export class DynamicComponent{
public bindedValue : Object = {
 value:''
 }
}

// at dynamic component template
<input type="text" [(ngModel)]="bindedValue.value"/>


//At parent component
this.currentComponent.instance.bindedValue= this.selectedValue;

Now bindedValue and selectedValue will have the same object reference. Both will hold the same value.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.