Lazar Ljubenović
Lazar Ljubenović

Reputation: 19754

Render instance of a component in Angular?

I've manually created an instance of a class. This class has a @Component decorator. How do I render its template?

@Component({ template: `hello {{ who }}` })
class Greeting {
  constructor (public who: string) { }
}

@Component({ template: `<ng-somehow-render [instance]="greeting"/>` })
class OtherComponent {

  public greeting: Greeting

  constructor () {
    this.greeting = new Greeting('world')
  }

}

Upvotes: 2

Views: 1559

Answers (1)

satanTime
satanTime

Reputation: 13539

Looks like you need a middleware component to render instances of another components.

it could be this one

@Component({
    selector: 'ng-somehow-render',
    template: '',
})
export class NgSomehowRenderComponent implements OnInit {
    @Input() instance: any;

    constructor (
        private cfr: ComponentFactoryResolver,
        private vcr: ViewContainerRef,
        private cdr: ChangeDetectorRef,
    ) {
    }

    public ngOnInit(): void {
        const componentFactory = this.cfr.resolveComponentFactory(this.instance.constructor);

        this.vcr.clear();
        const componentRef = this.vcr.createComponent(componentFactory);
        for (const key of Object.getOwnPropertyNames(this.instance)) {
            componentRef.instance[key] = this.instance[key];
        }
        this.cdr.detectChanges();
    }
}

Simply add its declaration into your modules.

BTW the Greeting component should be declared in your modules in entryComponents.

@NgModule({
  declarations: [AppComponent, Greeting, NgSomehowRenderComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent],
  entryComponents: [Greeting]
})

Because Angular will try to solve constructor dependencies you need to add @Optional() decorator there.

@Component({
  template: `hello {{ who }}`
})
export class Greeting {
  constructor(@Optional() public who: string) {}
}

profit.

You can check live demo here: https://codesandbox.io/s/jolly-villani-32m5w?file=/src/app/app.component.ts

All the things from the official doc, so you can use it without problems: https://angular.io/guide/dynamic-component-loader#resolving-components

Upvotes: 1

Related Questions