2

I have a <div> with a directive [appComponent] so I can create a component and append to it.

<div [appComponent]="component">

My directive is as follows:

@Directive({
  selector: '[appComponent]'
})
export class ComponentDirective implements OnChanges {
  @Input('appComponent') comp: any;
  private container;

  constructor(private elementRef: ElementRef, private renderer: Renderer2) {
    this.container = this.elementRef.nativeElement;
  }

  ngOnChanges(changes: SimpleChanges): void {
    const newComponent = this.renderer.createElement('new-component');
    this.renderer.appendChild(this.container, newComponent);
  }
}

And my new-component:

@Component({
  selector: 'new-component',
  templateUrl: './new-component.html',
  styleUrls: ['./new-component.scss']
})
export class NewComponent {
}

This component has contents inside. The element is created and appended to div, however, it's empty:

<div>
    <new-component _ngcontent-c3=""></new-component>
</div>

How to instantiate a component and append it to div? I'm using angular 7.

iPhoneJavaDev
  • 821
  • 5
  • 33
  • 78

2 Answers2

2

Try using ViewContainerRef and ComponentFactoryResolver,

let componentFactory = 
    this.componentFactoryResolver.resolveComponentFactory(NewComponent);
let componentInstance = 
    this.viewContainerRef.createComponent(componentFactory);
this.renderer.appendChild(this.container, 
    componentInstance.location.nativeElement);
-1

You don't need the ElementRef nor the Renderer2 for this.

Try this instead:

@Directive({
  selector: '[appComponent]'
})
export class ComponentDirective implements OnChanges {
  @Input('appComponent') comp: any;

  constructor(private componentFactoryResolver: ComponentFactoryResolver, public viewContainerRef: ViewContainerRef) {
  }

  ngOnChanges(changes: SimpleChanges): void {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(NewComponent);
    const componentRef = this.viewContainerRef.createComponent(componentFactory);
    this.viewContainerRef.insert(componentRef.hostView);
  }
}

One important thing to mention is, to make this work you have to add NewComponent to entryComponents as follows:

@NgModule({
  imports [...],
  entryComponents: [NewComponent],
  declarations: [NewComponent, ComponentDirective, ...],
  bootstrap: [...]
})
export class AppModule { }

Here is a working example: https://stackblitz.com/edit/angular-dbszef