File

libs/core/dynamic-form/src/services/component-loader/component-loader.service.ts

Index

Methods

Methods

Async getComponent
getComponent(config: literal type)

Gets a component and module reference

Parameters :
Name Type Optional Description
config literal type No

The config of the component, including the type (and name for custom components)

Returns : Promise<DfComponentModule>

Promise A promise with the component and module reference

import {
  createNgModule,
  inject,
  Injectable,
  Injector,
  isStandalone,
  NgModuleRef,
  Type
} from '@angular/core';
import { DfBaseConfig, NATIVE_DYNAMIC_FORM_COMPONENTS } from '../../base/base.model';
import { CUSTOM_COMPONENT_TYPE, CUSTOM_DYNAMIC_FORM_COMPONENT } from '../../base/custom.component';

interface DfComponentModule {
  component: Type<unknown>;
  moduleRef?: NgModuleRef<unknown>;
}

@Injectable()
export class DfComponentLoaderService {
  private injector = inject(Injector);
  private nativeComponents = inject(NATIVE_DYNAMIC_FORM_COMPONENTS);
  private customComponents =
    inject(CUSTOM_DYNAMIC_FORM_COMPONENT, {
      optional: true
    }) ?? [];

  /**
   * Gets a component and module reference
   * @param config The config of the component, including the `type` (and `name` for custom components)
   * @return Promise<DfComponentModule> A promise with the component and module reference
   */
  async getComponent(config: {
    type: DfBaseConfig['type'];
    name?: string;
  }): Promise<DfComponentModule> {
    if (config.type === CUSTOM_COMPONENT_TYPE) {
      if (!config.name) {
        throw new Error('Custom component name is required');
      }

      return this.retrieveCustomComponentModule(config.name);
    }

    return this.retrieveNativeComponentModule(config.type);
  }

  /**
   * Gets component type and compiles module reference if component is not standalone
   * @param component The dynamic form component to load (supports standalone components)
   * @param module The module. Optional if component is a standalone component
   * @return DfComponentModule A reference to the module and the component to compile
   */
  private getComponentModule(component: Type<unknown>, module?: Type<unknown>): DfComponentModule {
    if (!module) {
      if (!isStandalone(component)) {
        throw new Error(
          `Component "${component?.name}" is not an Angular Standalone component. Please provide its module.`
        );
      }
      return { component };
    }

    return {
      moduleRef: createNgModule(module, this.injector),
      component: component
    };
  }

  private async retrieveNativeComponentModule(type: string): Promise<DfComponentModule> {
    const config = this.nativeComponents[type];
    if (!config) {
      return Promise.reject(`The component ${type} is not registered`);
    }

    const result = await config.load();
    return this.getComponentModule(
      result[config.componentName as keyof typeof result],
      config.moduleName ? result[config.moduleName as keyof typeof result] : undefined
    );
  }

  private async retrieveCustomComponentModule(name: string): Promise<DfComponentModule> {
    const customComponent = this.customComponents?.find((c) => c.componentName === name);
    if (!customComponent) {
      throw new Error(`The custom component "${name}" is not registered`);
    }

    const result = await customComponent.load();
    return this.getComponentModule(
      result[customComponent.componentName],
      customComponent.moduleName ? result[customComponent.moduleName] : undefined
    );
  }
}

results matching ""

    No results matching ""