/**
* @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;
if (model) {
this.output = (model as Renderable).render<AngularDynamicOutput>(
this.globals || {},
this.vcr,
this.injector,
this.inner,
this.projectable,
);
if (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 || {});
if (operation) {
this.operation = operation as CrudOperationKeys;
}
this.subscribeEvents();
}
}
}
Source