How to render custom component in parent view component?

565 Views Asked by At

I'd like to render custom component inside mat-option. This is the code in my parent component:

  <mat-option *ngFor="let option of options" [value]="option.value">
   HERE I WOULD LIKE TO INJECT SOME COMPONENT
  </mat-option>

Let's assume that I have a component called CustomOptionView:

@Component({
    selector: 'custom-option-view',
    template: `<h1> {{ label }} </h1>`,
})
export class CustomOptionView{
@Input() label?: string;
}

And I would like to create that component manually in my child component like this:

const factory = this.componentFactoryResolver.resolveComponentFactory(CustomOptionView);

How Can I pass this instance to parent component and render it?

Why I am trying to do that? Because I would like to have options in selectlist that looks differently. One component needs to show icons and multiline text and other doesn't need it. I came to conclusion that I need a set of custom components that I could somehow inject to parent's html.

2

There are 2 best solutions below

3
Liero On BEST ANSWER

general API for dynamically creating a component

You can dynamically add a component at runtime using viewContainerRef.createComponent() API

See guide: https://angular.io/guide/dynamic-component-loader

ready to use solution


The above mentioned mechanism is already implemented in built in *ngComponentOutlet directive.

See docs: https://angular.io/api/common/NgComponentOutlet

basically, ngComponentOutlet takes the component type as a parameter.

@Component({
  selector: 'my-app',
  template: `<ng-container *ngComponentOutlet="dynamicComponentToLoad"></ng-container>
             <button (click)="switchComponent()">Switch components</button>`
})
export class AppComponent {
  // This field is necessary to expose HelloWorld to the template.
  dynamicComponentToLoad: Type<any> = Component1;

  switchComponent() {
     dynamicComponentToLoad = Component2;
  }
}

In you case it could look like this:

<mat-option *ngFor="let option of options" [value]="option.value">
   <ng-container *ngComponentOutlet="option.componentType; injector:createInjector(option)"></ng-container>
</mat-option>
5
Andrei On

you could use NgComponentOutletDirective to do that. example

 <mat-option *ngFor="let option of options" [value]="option.value">
     <ng-container *ngIf="option.type=='type1'">
        <ng-container *ngComponentOutlet="component1">
     </ng-container>

  </mat-option>