Problem loading a component when calling it in the main component in Angular 18

Discussão em 'Angular' iniciado por Blue Moon, Fevereiro 16, 2025.

  1. Blue Moon

    Blue Moon Guest

    I have defined several components, including Textbox, Autocomplete, and Button, and I want to use them in another component. My goal is to dynamically load a component in another component based on its name. To achieve this, I wrote the following code:

    I created a directive as follows:

    import { Directive, ViewContainerRef } from '@angular/core';

    @Directive({
    selector: '[appDynamicHost]',
    standalone: true
    })
    export class DynamicHostDirective {

    constructor(public viewContainerRef: ViewContainerRef) { }

    }



    I wrote a service as follows:

    import { Injectable, Type } from '@angular/core';
    import { PngAutoCompleteComponent } from '@components/components/png-auto-complete/png-auto-complete.component';
    import { PngButtonComponent } from '@components/components/png-button/png-button.component';
    import { PngTextboxComponent } from '@components/components/png-textbox/png-textbox.component';

    @Injectable({
    providedIn: 'root'
    })
    export class DynamicComponentService {

    constructor() { }

    private components: { [key: string]: Type<any> } = {
    'pngTextbox': PngTextboxComponent,
    'pngButton': PngButtonComponent,
    'pngAutoComplete':pngAutoCompleteComponent
    };

    getComponent(name: string): Type<any> | null {
    return this.components[name] || null;
    }

    }


    I implemented a dynamic component loader as follows:

    .ts file :

    import { Component, ComponentRef, ViewChild } from '@angular/core';
    import { DynamicComponentService } from '@services/dynamic-component.service';
    import { DynamicHostDirective } from 'src/app/directives/dynamic-host.directive';

    @Component({
    selector: 'app-dynamic-loader',
    standalone: true,
    imports: [],
    templateUrl: './dynamic-loader.component.html',
    styleUrl: './dynamic-loader.component.scss'
    })
    export class DynamicLoaderComponent {

    @ViewChild(DynamicHostDirective, { static: true }) dynamicHost!: DynamicHostDirective;

    private componentRef!: ComponentRef<any>;

    constructor(private dynamicService: DynamicComponentService) {
    }

    loadComponent(componentName: string, data: any) {
    const componentType = this.dynamicService.getComponent(componentName);

    if (!componentType) {
    console.error(`Component "${componentName}" not found!`);
    return;
    }

    const viewContainerRef = this.dynamicHost.viewContainerRef;
    viewContainerRef.clear();
    this.componentRef = viewContainerRef.createComponent(componentType);

    if (this.componentRef.instance) {
    this.componentRef.instance.data = data;
    }
    }

    getComponentData() {
    if (this.componentRef && this.componentRef.instance) {
    return this.componentRef.instance.data;
    }
    return null;
    }

    ngOnInit() {}
    }


    html file:

    <ng-template #dynamicHost></ng-template>


    Finally, I called the dynamic component loader in the main component.

    .ts file:

    import { Component, OnInit, ViewChild } from '@angular/core';
    import { DynamicLoaderComponent } from '@components/components/dynamic-loader/dynamic-loader.component';


    @Component({
    selector: 'app-form-001',
    standalone: true,
    imports: [DynamicLoaderComponent],
    templateUrl: './form-001.component.html',
    styleUrl: './form-001.component.scss'
    })

    export class Form001Component implements OnInit{

    @ViewChild('dynamicLoaderx') dynamicLoader!: DynamicLoaderComponent;

    // constructor (private dynamicLoader: DynamicLoaderComponent) {}

    ngOnInit(): void {
    this.dynamicLoader.loadComponent('pngTextbox', { invoiceNumber: '12345', date: '1402/12/01' });
    }
    }



    .hrml file:

    <app-dynamic-loader #dynamicLoaderx></app-dynamic-loader>


    I am not sure what I did wrong, but I am getting the following error:

    ERROR TypeError: Cannot read properties of undefined (reading 'loadComponent')
    at _Form001Component.ngOnInit

    Continue reading...

Compartilhe esta Página