All files / src/lib/components/model-renderer model-renderer.component.ts

41.17% Statements 7/17
0% Branches 0/9
50% Functions 1/2
37.5% Lines 6/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97                    5x 5x 5x     5x                                                                           5x           1x                                                                          
/**
 * @module module:lib/components/model-renderer/model-renderer.component
 * @description Model renderer component module.
 * @summary Exposes `ModelRendererComponent` which dynamically renders UI components
 * from model definitions using the `NgxRenderingEngine`. It handles model changes,
 * event subscription and lifecycle for the rendered output.
 *
 * @link {@link ModelRendererComponent}
 */
 
import { Component, Input } from '@angular/core';
import { Model, Primitives, sf } from '@decaf-ts/decorator-validation';
import { AngularEngineKeys } from '../../engine/constants';
import { AngularDynamicOutput } from '../../engine/interfaces';
import { Renderable, CrudOperationKeys } from '@decaf-ts/ui-decorators';
import { NgxRenderableComponentDirective } from '../../engine/NgxRenderableComponentDirective';
 
/**
 * @description Component for rendering dynamic models
 * @summary This component is responsible for dynamically rendering models,
 * handling model changes, and managing event subscriptions for the rendered components.
 * It uses the NgxRenderingEngine to render the models and supports both string and Model inputs.
 * @class
 * @template M - Type extending Model
 * @param {Injector} injector - Angular Injector for dependency injection
 * @example
 * <ngx-decaf-model-renderer
 *   [model]="myModel"
 *   [globals]="globalVariables"
 *   (listenEvent)="handleEvent($event)">
 * </ngx-decaf-model-renderer>
 * @mermaid
 * sequenceDiagram
 *   participant App
 *   participant ModelRenderer
 *   participant RenderingEngine
 *   participant Model
 *   App->>ModelRenderer: Input model
 *   ModelRenderer->>Model: Parse if string
 *   Model-->>ModelRenderer: Parsed model
 *   ModelRenderer->>RenderingEngine: Render model
 *   RenderingEngine-->>ModelRenderer: Rendered output
 *   ModelRenderer->>ModelRenderer: Subscribe to events
 *   ModelRenderer-->>App: Emit events
 */
@Component({
  standalone: true,
  imports: [],
  selector: 'ngx-decaf-model-renderer',
  templateUrl: './model-renderer.component.html',
  styleUrl: './model-renderer.component.scss',
  host: { '[attr.id]': 'uid' },
})
export class ModelRendererComponent<M extends Model> extends NgxRenderableComponentDirective {
  /**
   * @description Set if render content projection is allowed
   * @default true
   */
  @Input()
  override projectable: boolean = true;
 
  // private injector: Injector = inject(Injector);
 
  // constructor() {}
 
  /**
   * @description Refreshes the rendered model
   * @param {string | M} model - The model to be rendered
   */
  override async render(model: string | M): Promise<void> {
    model = typeof model === Primitives.STRING ? (Model.build({}, String(model)) as M) : model;
 
    Iif (model) {
      this.output = (model as Renderable).render<AngularDynamicOutput>(
        this.globals || {},
        this.vcr,
        this.injector,
        this.inner,
        this.projectable,
      );
      Iif (this.output?.inputs)
        this.rendererId = sf(
          AngularEngineKeys.RENDERED_ID,
          (this.output.inputs as Record<string, unknown>)['rendererId'] as string,
        );
      this.instance = this.output?.component;
      const { operation } = this.globals || {};
      // const {inputs} = this.output;
      // await this.initProps(inputs || {});
      Iif (operation) {
        this.operation = operation as CrudOperationKeys;
      }
      this.subscribeEvents();
    }
  }
}