npm.io
2.10.106 • Published 15h ago

@eqproject/eqp-dynamic-module

Licence
Version
2.10.106
Deps
16
Size
15.4 MB
Vulns
2
Weekly
0

@eqproject/eqp-dynamic-module

npm version Angular

Libreria Angular 15 per la creazione, visualizzazione e gestione di form dinamiche con configuratore no-code.
Angular 15 library for building, rendering and managing dynamic forms with a no-code configurator.

Guida utente / User Guide →


Changelog

v2.10.104

  • Bugfix trigger — condizioni multiple valutate come indipendenti: checkTriggers applicava ogni condizione isolatamente, ignorando booleanlogicoperator (AND/OR/AND NOT/OR NOT): un trigger con più condizioni e almeno un OR poteva non scattare mai o scattare quando non doveva. Introdotto evaluateTriggerCondition() che valuta la singola condizione e combina il risultato con quello accumulato secondo l'operatore booleano dichiarato tra le condizioni.
  • Bugfix configurator — salvataggio Trigger/ActionButton non persisteva le modifiche: saveActionButtons/saveTriggers cercavano l'elemento esistente con .find() e riassegnavano la variabile locale invece dell'elemento nell'array (existsTrigger = element non scriveva su form.Triggers), per cui le modifiche a un trigger o action button già esistente venivano perse al salvataggio. Ora si usa .findIndex() e si scrive sull'array tramite l'indice.
  • Trigger — descrizione obbligatoria: il campo "Descrizione" del trigger e il "Tipo Trigger" sono ora obbligatori per il salvataggio; il pulsante "Salva" resta disabilitato con un messaggio esplicativo finché non sono valorizzati.
  • Trigger — gestione tipo trigger non più presente nel catalogo: se un trigger salvato in precedenza referenzia un execution non più presente tra le formule disponibili (es. rimosso/rinominato), il componente non blocca più l'inizializzazione: la select "Tipo Trigger" resta popolata e utilizzabile per la riassegnazione.
  • Trigger/ActionButton — cache dei moduli collegati: getAllModules() (usato per i campi di tipo DMMODULE) veniva richiamato ad ogni cambio di formula anche quando i moduli erano già stati scaricati. Aggiunta ensureModulesLoaded() che riusa this.forms già caricato invece di ripetere la chiamata all'endpoint.
  • Trigger fix — multiple conditions evaluated independently: checkTriggers evaluated each condition in isolation, ignoring booleanlogicoperator (AND/OR/AND NOT/OR NOT): a trigger with multiple conditions and at least one OR could either never fire or fire when it shouldn't. Introduced evaluateTriggerCondition(), which evaluates a single condition and combines it with the accumulated result using the declared boolean operator between conditions.
  • Configurator fix — saving a Trigger/ActionButton didn't persist changes: saveActionButtons/saveTriggers looked up the existing element with .find() and reassigned the local variable instead of the array element (existsTrigger = element never wrote back to form.Triggers), so edits to an already-existing trigger or action button were lost on save. Now uses .findIndex() and writes to the array via the index.
  • Trigger — mandatory description: the trigger's "Descrizione" field and "Tipo Trigger" are now required to save; the "Salva" button stays disabled with an explanatory message until both are set.
  • Trigger — handling a trigger type no longer in the catalog: if a previously-saved trigger references an execution no longer present among the available formulas (e.g. removed/renamed), the component no longer blocks initialization: the "Tipo Trigger" select stays populated and usable for reassignment.
  • Trigger/ActionButton — linked-modules cache: getAllModules() (used for DMMODULE-type fields) was being called on every formula change even when the modules had already been downloaded. Added ensureModulesLoaded(), which reuses the already-loaded this.forms instead of repeating the endpoint call.
v2.10.87
  • Bugfix configurator — sezione "Generale" assente per 5 tipi di campo: durante il lavoro di potenziamento grafico (v2.10.68–v2.10.70), i tipi ActionButtonField, ImageField, ImageWithMarkersField, ListValueField e ImageSelectorField avevano ricevuto la sezione "Grafica" nel tab "Stile Compilazione" del configuratore, ma la sezione "Generale" (Larghezza campo, Visibile, VisibleIf, Tooltip, Tipo di invisibilità, Mantieni il valore) era stata rimossa per errore. Ripristinata per tutti e 5 i tipi.
  • Bugfix configurator — "Generale" section missing for 5 field types: during the graphical enhancement work (v2.10.68–v2.10.70), ActionButtonField, ImageField, ImageWithMarkersField, ListValueField and ImageSelectorField received the "Grafica" section in the configurator's "Stile Compilazione" tab, but the "Generale" section (field width, visibility, VisibleIf, tooltip, invisibility type, maintain value) was accidentally removed. Restored for all 5 field types.
v2.10.86
  • Bugfix loop infinito ListValueField: FormControl.setValue() notificava il callback _onChange del NgModel registrato tramite [formControlName] sul mat-checkbox, causando ngModelChangeupdateSelected()setFormControlValue() in ricorsione infinita. Aggiunto { emitModelToViewChange: false } a setFormControlValue() per interrompere il ciclo. Fix correlati: updateSelected() ora restituisce null (non []) per campi single-choice senza selezione, evitando instabilità Angular CD da [] !== []; resetArrayData() chiama updateSelected(false) per non emettere recordChange durante il rebuild delle opzioni; updateField() distingue formula-per-valore da formula-per-opzioni nei campi DataGetterType=Formula.
  • Bugfix loop infinito onRecordChange: aggiunta guardia di rientranza _recordChanging con try/finally in add-form-record.onRecordChange() per prevenire ricorsione da campi formula concatenati (es. campo numerico → campo elenco valorizzato dalla formula del primo).
  • Bugfix loop in anteprima — DynAttachment.ButtonKey null: nei template image-field-template e image-with-markers-field-template, la valutazione di field.DynAttachment.ButtonKey in *ngIf lanciava eccezione quando DynAttachment era null (campo senza immagine caricata), innescando un loop di Angular CD. Sostituito con field.DynAttachment?.ButtonKey.
  • Fix posizione dialog DataGetter: la modale del Query Editor aperta con "Modifica" nel configuratore compariva a metà pagina. Aggiunti position: { top: '20px' } e maxHeight: '90vh' per allinearla al comportamento di tutte le altre dialog.
  • Bugfix infinite loop ListValueField: FormControl.setValue() was notifying the _onChange callback of the NgModel registered via [formControlName] on mat-checkbox, causing ngModelChangeupdateSelected()setFormControlValue() in infinite recursion. Added { emitModelToViewChange: false } to setFormControlValue() to break the cycle. Related fixes: updateSelected() now returns null (not []) for single-choice fields with no selection, preventing Angular CD instability from [] !== []; resetArrayData() calls updateSelected(false) to avoid emitting recordChange during option rebuild; updateField() now distinguishes formula-for-value from formula-for-options in DataGetterType=Formula fields.
  • Bugfix infinite loop onRecordChange: added _recordChanging re-entrancy guard with try/finally in add-form-record.onRecordChange() to prevent recursion from chained formula fields (e.g. numeric field → list field driven by the first field's formula).
  • Bugfix preview loop — DynAttachment.ButtonKey null: in image-field-template and image-with-markers-field-template, evaluating field.DynAttachment.ButtonKey in *ngIf threw an exception when DynAttachment was null (field with no image loaded), triggering an Angular CD loop. Replaced with field.DynAttachment?.ButtonKey.
  • Fix DataGetter dialog position: the Query Editor modal opened via "Modifica" in the configurator was appearing at mid-page. Added position: { top: '20px' } and maxHeight: '90vh' to align it with all other dialogs.
v2.10.85
  • Bugfix loop infinito (approccio corretto): il loop di v2.10.84 era asincrono: setValue chiama writeValue sui ControlValueAccessor di Angular Material che emettono eventi nel tick successivo, quando la guardia di rientranza era già rilasciata. Soluzione definitiva: il validator required ora legge direttamente da record[field.Name] tramite closure (anziché da control.value); in onRecordChange() viene chiamato updateValueAndValidity({ emitEvent: false }) — che ri-esegue i validator senza invocare writeValue — eliminando alla radice ogni possibilità di cascade.
  • Bugfix infinite loop (correct approach): the v2.10.84 loop was asynchronous: setValue calls writeValue on Angular Material ControlValueAccessors which emit events on the next tick, after the re-entrancy guard was already released. Definitive fix: the required validator now reads directly from record[field.Name] via closure (instead of control.value); onRecordChange() calls updateValueAndValidity({ emitEvent: false }) — which re-runs validators without invoking writeValue — eliminating any cascade at the root.
v2.10.84
  • Bugfix loop infinito onRecordChange: la sincronizzazione dei FormControl introdotta in v2.10.83 causava un loop: setValue invoca writeValue sui ControlValueAccessor (es. mat-datepicker), che emettono (dateChange)/(ngModelChange)recordChangeonRecordChange di nuovo, all'infinito. Aggiunta una guardia di rientranza (_isInRecordChange) con try/finally che interrompe il ciclo. La sincronizzazione dei FormControl resta attiva e la validazione required funziona correttamente.
  • Bugfix infinite loop onRecordChange: the FormControl sync introduced in v2.10.83 caused an infinite loop: setValue calls writeValue on ControlValueAccessors (e.g. mat-datepicker), which emit (dateChange)/(ngModelChange)recordChangeonRecordChange again, endlessly. Added a re-entrancy guard (_isInRecordChange) with try/finally that breaks the cycle. FormControl sync remains active and required validation works correctly.
v2.10.83
  • Bugfix validazione form — campi obbligatori valorizzati via formula/ActionButton: quando un campo con required veniva impostato tramite formula o ActionButton, il valore compariva visivamente ma il FormControl Angular rimaneva non aggiornato, lasciando il form invalido finché l'utente non interagiva manualmente col campo. Ora onRecordChange() risincronizza tutti i FormControl dal record dopo ogni aggiornamento formula, rendendo la validazione coerente con il valore visualizzato.
  • Bugfix form validation — required fields set via formula/ActionButton: when a required field was populated by a formula or ActionButton, the value appeared visually but the Angular FormControl was never updated, keeping the form invalid until the user manually interacted with the field. onRecordChange() now re-syncs all FormControl values from the record after every formula update, making validation consistent with the displayed value.
v2.10.81
  • Bugfix configurator — DataGetter null dopo decode Base64: quando il campo DataGetterValueBase64String decodifica in un JSON con DataGetter: null, viene ora creato un oggetto DataGetter vuoto anziché proseguire con null, evitando errori a runtime nel configuratore.
  • Bugfix add-form-recordactionButtons null: se l'input actionButtons arriva null al componente, viene ora inizializzato a un array vuoto prima del filtraggio, prevenendo un'eccezione al caricamento del record.
  • Bugfix configurator — DataGetter null after Base64 decode: when DataGetterValueBase64String decodes to a JSON with DataGetter: null, a new empty DataGetter object is now created instead of proceeding with null, preventing runtime errors in the configurator.
  • Bugfix add-form-recordactionButtons null: if the actionButtons input arrives as null, it is now initialized to an empty array before filtering, preventing an exception on record load.
v2.10.79
  • DataGetter V2 — selezione automatica colonna singola: quando il flusso V2 genera una sola columnKey, essa viene assegnata automaticamente a DataGetterColumnForce senza che l'utente debba selezionarla manualmente dalla dropdown.
  • DataGetter V2 — single column auto-selection: when the V2 flow produces exactly one columnKey, it is automatically assigned to DataGetterColumnForce without requiring manual selection from the dropdown.
v2.10.77
  • DataGetter V2 — DataGetterColumnForce come stringa: onAiDataGetterOut ora salva DataGetterColumnForce come stringa chiave (non come oggetto), allineandosi al formato atteso da eqp-select. Il valore pre-selezionato nella dropdown compare automaticamente dopo il flusso AI.
  • DataGetter V2 — DataGetterColumnForce as string: onAiDataGetterOut now stores DataGetterColumnForce as a key string (not as an object), matching the format expected by eqp-select. The pre-selected value in the dropdown appears automatically after the AI flow.
v2.10.76
  • DataGetter V2 — createColumnKeys retrocompatibile: add-form-field ora rileva DataGetterCodeVersion=2 e legge selectedFields da queryCommandDatabaseConfiguration.selectedFields invece che dal livello radice; fallback su PropertyName se CurrentTranslate è assente.
  • DataGetter V2 — createColumnKeys backward-compatible: add-form-field now detects DataGetterCodeVersion=2 and reads selectedFields from queryCommandDatabaseConfiguration.selectedFields instead of the root level; falls back to PropertyName when CurrentTranslate is missing.
v2.10.74 / v2.10.75
  • DataGetter AI — nuova modalità "Da database" (DataGetterType=3): aggiunto campo DataGetterSpeechText nel modello DataGetter. Il configurator AI può creare campi con recupero dati da database impostando un prompt testuale: al caricamento del form, il componente QueryEditor esterno viene invocato silenziosamente, elabora il prompt via AI e popola automaticamente DataGetterValue, DataGetterCardinality=1, DataGetterHasResetButton=true e DataGetterColumnForce (se il risultato ha un solo campo selezionato).
  • DataGetterCodeVersion V2 — retrocompatibilità in lettura: il DbgetterComponent rileva automaticamente i campi con DataGetterCodeVersion=2 (formato Omnisearch AI) ed esegue un unwrap trasparente della struttura queryCommandDatabaseConfiguration al formato V1, senza impatto sui campi legacy. Il DataGetterCodeVersion=2 viene propagato al componente QueryEditor esterno tramite config.DataGetterCodeVersion per consentire al client ospitante di attivare il flusso V2 in lettura.
  • AI DataGetter — new "Da database" mode (DataGetterType=3): added DataGetterSpeechText field to the DataGetter model. The AI configurator can create database-getter fields with a natural-language prompt: on form load, the external QueryEditor component is invoked silently, processes the prompt via AI and automatically populates DataGetterValue, DataGetterCardinality=1, DataGetterHasResetButton=true and DataGetterColumnForce (if a single output field is returned).
  • DataGetterCodeVersion V2 — backward-compatible read flow: DbgetterComponent now auto-detects fields with DataGetterCodeVersion=2 (Omnisearch AI format) and transparently unwraps the queryCommandDatabaseConfiguration structure to the V1 format, with zero impact on legacy fields. DataGetterCodeVersion=2 is forwarded to the external QueryEditor component via config.DataGetterCodeVersion to enable the V2 read flow on the host application side.
v2.10.70
  • Theming configurator — nuovi input: aggiunto [configuratorThemeCss] che accetta direttamente il testo di un file CSS con le dichiarazioni delle variabili --conf-*. Permette di portare il tema dall'esterno come file statico senza hardcodare valori TypeScript. Se entrambi gli input sono presenti, configuratorTheme sovrascrive configuratorThemeCss per le chiavi in conflitto.
  • Theming configurator — nuove variabili CSS: --conf-stepper-header-bg (sfondo zona step superiore), --conf-stepper-content-bg (sfondo zona inferiore), --conf-step-icon-edit-bg (sfondo pallini step completati), --conf-hint-btn-bg / --conf-hint-btn-hover-bg (bottone suggerimento rapido), --conf-btn-color (colore testo bottoni con sfondo gradiente).
  • Theming configurator — forzatura !important: tutti i valori iniettati tramite tema esterno sono ora applicati con !important, rendendo il sistema di theming l'unico canale valido per sovrascrivere i colori.
  • Theming configurator — --conf-btn-color: il colore del testo dei bottoni attivi (sfondo gradiente) è ora templatizzabile e forzato con !important per resistere a override CSS provenienti dall'applicazione ospitante.
  • New theming input: added [configuratorThemeCss] accepting a CSS text string with --conf-* variable declarations. Enables external theme files without TypeScript hardcoding. When both inputs are present, configuratorTheme overrides configuratorThemeCss for conflicting keys.
  • New CSS variables: --conf-stepper-header-bg, --conf-stepper-content-bg, --conf-step-icon-edit-bg, --conf-hint-btn-bg, --conf-hint-btn-hover-bg, --conf-btn-color.
  • !important enforcement: all externally-injected theme values are now set with !important, making the theming system the sole valid override channel.
v2.10.65
  • TextField — icona opzionale: aggiunta la possibilità di associare un'icona Material Icons al campo di testo. Le nuove proprietà IconName (stringa) e IconPosition (enum: 1=Sinistra/prefix, 2=Destra/suffix) sono opzionali e retrocompatibili (null sui form esistenti). Configurabili nel builder tramite il toggle "Icona" nella sezione Specifiche del campo.
  • TextField — optional icon: added support for a Material Icons icon on text fields. New properties IconName (string) and IconPosition (enum: 1=Left/prefix, 2=Right/suffix) are optional and backward-compatible (null on existing forms). Configurable in the builder via the "Icona" toggle in the field's Specifiche section.
v2.10.64
  • Bugfix configurator: se il campo Code del form risulta null al momento del salvataggio (scenario: form creato con AI senza salvataggio intermedio), ora viene generato automaticamente da Name prima dell'invio al server.
v2.10.63
  • README riscritto in formato bilingue (italiano completo + inglese completo).
  • Aggiunto USERGUIDE.md con guida pratica per scenari d'uso comuni e sezione prompt AI di esempio.
  • USERGUIDE.md incluso nel pacchetto npm tramite ng-package.json assets.
v2.10.62
  • Migrazione da tmw-picker 1.0.x a 1.1.0: NgModule → standalone components, moment.js → Luxon, aggiornamento di tutti i token formato data (DD/MM/YYYYdd/MM/yyyy).
  • Rimossi input inutilizzati: answerToDuplicateId da eqp-dynamic-module, ProjectName da eqp-dynamic-module-configurator.
  • Documentazione NPM riscritta completamente (bilingue IT/EN).
v2.10.60
  • Aggiornamenti interni e correzioni bug.

Versione italiana


Panoramica

@eqproject/eqp-dynamic-module espone due componenti pubblici:

Componente Scopo
<eqp-dynamic-module> Visualizzatore, compilatore, lista, filtro e grafici a runtime
<eqp-dynamic-module-configurator> Builder no-code per creare e modificare le definizioni form

Le form sono strutture JSON salvate lato server e recuperate a runtime. La libreria gestisce rendering, validazione, recupero dati, operazioni CRUD e funzionalità avanzate come formule, trigger, action button e speech-to-text.


Prerequisiti
npm install @angular/cdk@^15.1.2 @angular/material@^15.1.2 @angular/material-luxon-adapter@^15.2.9 --legacy-peer-deps
npm install @angular-material-components/datetime-picker@^15.0.0 @angular-material-components/moment-adapter@^15.0.0 --legacy-peer-deps
npm install moment@^2.29.4 sweetalert2@^11.4.24 --legacy-peer-deps

Tutti i comandi npm install per questa libreria richiedono il flag --legacy-peer-deps.


Installazione
npm install @eqproject/eqp-dynamic-module --legacy-peer-deps

Configurazione del modulo
import { EqpDynamicModuleModule } from '@eqproject/eqp-dynamic-module';

@NgModule({
  imports: [
    EqpDynamicModuleModule
  ]
})
export class AppModule {}

In angular.json, aggiungi il tema Material agli stili:

"styles": [
  "node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
  "src/styles.css"
]

Componenti
eqp-dynamic-module — Visualizzatore form

Visualizza una form dinamica in una delle modalità disponibili.

Utilizzo base

import { DynamicModuleGeneralConfig, DynamicModuleViewModeEnum } from '@eqproject/eqp-dynamic-module';

generalConfig = new DynamicModuleGeneralConfig(
  'https://tua-api.esempio.it/api',
  this.userToken,
  this.context,
  null
);
<eqp-dynamic-module
  [configurations]="generalConfig"
  [formID]="'id-del-form'"
  [starterViewMode]="DynamicModuleViewModeEnum.LIST"
  [userID]="currentUser.id"
  (saveRecord)="onSalvataggio($event)"
  (afterSaveRecord)="dopoSalvataggio($event)">
</eqp-dynamic-module>

Input

Input Tipo Default Descrizione
configurations DynamicModuleGeneralConfig Obbligatorio. Configurazione connessione server.
formID string Obbligatorio. ID del form da visualizzare.
starterViewMode DynamicModuleViewModeEnum LIST Modalità iniziale.
userID string "0" ID utente per il salvataggio record.
orgaID string "0" ID organizzazione.
showTitle boolean true Mostra/nasconde il nome del form.
showBackButton boolean true Mostra/nasconde il pulsante indietro.
showSaveButton boolean true Mostra/nasconde il pulsante salva.
values Record[] null Record pre-caricati per la modalità LIST.
FormJSON string "" JSON del form per la modalità REPAIR.
formulaObject any {} Oggetto contesto per le formule (es. { role, user }).
selectedRecord Record | string null Record pre-selezionato (oggetto o ID).
externalButtons RecordButton[] [] Pulsanti extra nel menu azioni record.
actionButtons ActionButton[] [] Pulsanti azione per i campi di tipo Bottone.
defaultListActions DynamicModuleListFormRecordActionsDefault tutti true Azioni default lista: add, view, edit, duplicate, delete, graphs.
listViewRecordTitle string[] [] Chiavi dei campi che compongono il titolo accordion.
defaultListViewFunction Function null Funzione custom al caricamento della lista.
onSaveBackToList boolean false Torna alla LIST dopo il salvataggio.
onBackTo DynamicModuleViewModeEnum null Modalità di destinazione del pulsante indietro.
numberOfColumns number 3 Numero di colonne del layout.
showHiddenFields boolean true Mostra/nasconde i campi marcati come nascosti.
filterResultViewMode DynamicModuleFilterResultViewModeEnum INTERNAL_EQPTABLE Modalità visualizzazione risultati filtro.
additionalParams any null Parametri extra per le chiamate filtro server.
additionalInfo any null Dati extra per operazioni client-side.
prefilterParams any null Parametri pre-filtro.
updateInfo any null Dati per aggiornare i valori delle risposte.
contestualizationParams any null Parametri di contestualizzazione della lista risultati.
showNewSearchButton boolean true Mostra/nasconde il pulsante "nuova ricerca".
highlightFilter any Configurazione evidenziazione righe/campi.
isDraggableListView boolean true Abilita drag-and-drop nella lista.
Statistic FilterStatistic null Configurazione statistiche e filtri.
QueryEditorComponent any Componente query editor custom per i lookup.
debugMode boolean false Abilita log dettagliati in console.

Output

Output Payload Descrizione
(saveRecord) Record Emesso al salvataggio senza endpoint configurato.
(afterSaveRecord) Record Emesso dopo la chiamata server di salvataggio.
(deleteRecord) Record Emesso all'eliminazione senza endpoint configurato.
(afterDeleteRecord) Record Emesso dopo la chiamata server di eliminazione.
(SaveJSON) string Emesso all'esportazione del JSON del form.
(afterFilter) DynRecord[] Emesso dopo l'applicazione di un filtro.
(dragStarted) Record Emesso all'inizio di un drag.
(dragReleased) void Emesso al rilascio del drag.
(clickDragIndicator) Record Emesso al click sull'icona drag.
(out) eventOut Output generico per comunicazione esterna.
(fireTrigger) FireTrigger Emesso quando scatta un trigger.
(afterOutputExternalFilters) FilterStatistic Emesso dopo filtri esterni applicati.

eqp-dynamic-module-configurator — Builder form

Designer no-code per creare e modificare definizioni form.

Modalità d'uso

// Nuovo form
const specific = new DynamicModuleConfiguratorSpecificConfig();
specific.UserID = this.currentUser.id;
specific.orgaID = this.currentOrga.id;
const general = new DynamicModuleGeneralConfig(this.baseServerUrl, this.userToken, this.context, null);
this.config = new DynamicModuleConfiguratorConfig(general, specific);
<!-- Nuovo form -->
<eqp-dynamic-module-configurator
  *ngIf="config"
  [configurations]="config"
  (saveFormEvent)="onSalvaForm($event)">
</eqp-dynamic-module-configurator>

<!-- Modifica form esistente -->
<eqp-dynamic-module-configurator
  *ngIf="config"
  [configurations]="config"
  [formID]="formID"
  (saveFormEvent)="onSalvaForm($event)">
</eqp-dynamic-module-configurator>

<!-- Esportazione -->
<eqp-dynamic-module-configurator
  [configurations]="config"
  [formID]="formID"
  [viewMode]="'Export'"
  (saveFormEvent)="onSalvaForm($event)">
</eqp-dynamic-module-configurator>

<!-- Importazione da JSON -->
<eqp-dynamic-module-configurator
  [configurations]="config"
  [formID]="null"
  [viewMode]="'Export'"
  (saveFormEvent)="onSalvaForm($event)">
</eqp-dynamic-module-configurator>

Input

Input Tipo Default Descrizione
configurations DynamicModuleConfiguratorConfig Obbligatorio. Contenitore configurazione.
formID string null ID del form da modificare. null crea un nuovo form.
viewMode string "addOrEdit" "addOrEdit" per creare/modificare, "Export" per esportare/importare.
fieldsExtraConfig FieldExtraConfig[] Configurazione extra per campi specifici.
triggers any Definizioni trigger disponibili nell'editor.
actionButtons any Definizioni action button disponibili.
contestualization Contestualization[] Opzioni di contestualizzazione per lookup e filtri.
formulaObject any Contesto per l'anteprima delle formule.
QueryEditorComponent DynamicLoaderDirectiveData Componente query editor custom.
debugMode boolean false Abilita log dettagliati.
configuratorTheme Record<string, string> | null null Override delle variabili CSS del tema tramite oggetto TypeScript.
configuratorThemeCss string | null null Override delle variabili CSS del tema tramite stringa CSS (es. contenuto di un file .css).

Output

Output Payload Descrizione
(saveFormEvent) Form Emesso al salvataggio senza endpoint configurato.
(afterSaveFormEvent) Form Emesso dopo la chiamata server di salvataggio.
(out) eventOut Output generico per comunicazione esterna.
(fireTrigger) FireTrigger Emesso quando scatta un trigger.

Theming

Il configurator espone un sistema di temi basato su CSS custom properties. Tutti i valori iniettati tramite tema sono applicati con !important e non possono essere sovrascritti dall'esterno se non attraverso questi input.

<!-- Opzione A: oggetto TypeScript -->
<eqp-dynamic-module-configurator
  [configurations]="config"
  [configuratorTheme]="{ '--conf-gradient': 'linear-gradient(to right, #1565c0, #0288d1)', '--conf-bg-page': '#f0f6fb' }">
</eqp-dynamic-module-configurator>

<!-- Opzione B: file CSS caricato come stringa -->
<eqp-dynamic-module-configurator
  [configurations]="config"
  [configuratorThemeCss]="themeCssString">
</eqp-dynamic-module-configurator>

Formato del file CSS per configuratorThemeCss (nessun selettore richiesto):

--conf-gradient:           linear-gradient(to right, #1565c0, #0288d1);
--conf-bg-page:            #f0f6fb;
--conf-btn-color:          #ffffff;

Variabili disponibili:

Variabile Default Descrizione
--conf-gradient gradiente viola-blu Sfondo bottoni e header
--conf-bg-page #f5f5f5 Sfondo generale pagina/stepper
--conf-radius 10px Border radius bottoni
--conf-modal-radius 12px Border radius modali
--conf-accent #693DDA Colore accento (bordi, focus)
--conf-primary #1E31EB Colore primario
--conf-step-selected #643cda Freccia step selezionato
--conf-step-edit #3034e7 Freccia step completato
--conf-stepper-header-bg ereditato da --conf-bg-page Sfondo zona superiore (header stepper)
--conf-stepper-content-bg ereditato da --conf-bg-page Sfondo zona inferiore (form e bottoni)
--conf-step-icon-edit-bg ereditato da --conf-step-edit Sfondo pallini step completati
--conf-btn-color #ffffff Colore testo bottoni attivi (sfondo gradiente)
--conf-hint-btn-bg #2563eb Sfondo bottone suggerimento rapido (lampadina)
--conf-hint-btn-hover-bg #1d4ed8 Sfondo lampadina al hover
--conf-table-header-bg variabile SCSS Sfondo header tabella campi
--conf-search-bg variabile SCSS Sfondo campo di ricerca
--conf-table-bg #ffffff Sfondo righe tabella
--conf-card-bg #ffffff Sfondo card
--conf-font-family inherit Font dell'intero configurator

Modelli di configurazione
DynamicModuleGeneralConfig
const general = new DynamicModuleGeneralConfig(
  'https://api.esempio.it/api', // baseServerUrl
  userToken,                    // token autenticazione
  context,                      // oggetto Context
  null                          // EndPointConfiguration (null = usa default)
);
Proprietà Tipo Descrizione
baseServerUrl string URL base API. Usato per costruire automaticamente gli endpoint se endPointConfiguration è null.
userToken string Token di autenticazione inviato con ogni chiamata.
endPointConfiguration EndPointConfiguration | null Override completo degli endpoint. null usa le rotte standard.
context Context Contesto applicativo.
DynamicModuleListFormRecordActionsDefault
const actions = new DynamicModuleListFormRecordActionsDefault();
actions.add       = true;   // Pulsante "Aggiungi" nell'header lista
actions.view      = true;   // Visualizza record (solo lettura)
actions.edit      = true;   // Modifica record
actions.duplicate = false;  // Duplica record
actions.delete    = true;   // Elimina record
actions.graphs    = false;  // Grafici record

Modalità di visualizzazione
import { DynamicModuleViewModeEnum } from '@eqproject/eqp-dynamic-module';

enum DynamicModuleViewModeEnum {
  NONE            = 0,  // Nessuna visualizzazione
  VIEW            = 1,  // Sola lettura
  COMPILE         = 2,  // Compilazione / modifica
  LIST            = 3,  // Lista record
  REPAIR          = 4,  // Revisione form
  LISTWIEW        = 5,  // Lista compatta alternativa
  FILTER          = 6,  // Filtro / ricerca
  GRAPHS          = 7,  // Statistiche e grafici
  HLIST           = 8,  // Lista orizzontale
  EXTERNAL_FILTER = 9   // Filtro guidato dal componente padre
}

Configurazione endpoint

Per default la libreria costruisce tutti gli URL dagli endpoint a partire da baseServerUrl. Passa un EndPointConfiguration custom per sovrascrivere singole rotte.

import { EndPointConfiguration, EndPointData, RequestMethodEnum, ParamTypeEnum } from '@eqproject/eqp-dynamic-module';

const endPoints = new EndPointConfiguration();
endPoints.Records.SaveEndPoint = new EndPointData();
endPoints.Records.SaveEndPoint.Url = 'https://custom-api.esempio.it/records/save';
endPoints.Records.SaveEndPoint.RequestMethod = RequestMethodEnum.POST;
endPoints.Records.SaveEndPoint.Params = [{
  ParamName: 'orgId',
  ParamValue: this.orgaId,
  ParamType: ParamTypeEnum['Query param']
}];

Endpoint Records disponibili: GetWithContextualizationByFormCodeEndPoint, GetByFormIDEndPoint, GetByFormCodeEndPoint, GetAllByEntAndUserIDEndPoint, GetByIDEndPoint, SaveEndPoint, DuplicateEndPoint, DeleteEndPoint, RepairEndPoint, ApplyFilter, GetAllAttachmentsEndPoint.

Endpoint Forms disponibili: GetByIDEndPoint, GetAllFormEndPoint, GetByIDAndVersionEndPoint, SaveEndPoint, SaveAttachmentEndPoint, ExportByIDEndPoint, GetAttachmentWithBases64, SpeechToFormEditEndPoint.


Modelli dati
Record
Proprietà Tipo Descrizione
ID string Identificatore unico.
EntID string ID del form (entità) di appartenenza.
Version number Versione del form al momento della compilazione.
userID string ID utente che ha creato il record.
AnswerDate string Data di compilazione (ISO).
HTMLreadableValues string Valori in formato HTML leggibile.
AdditionalParams any Parametri aggiuntivi.
AdditionalInfo any Informazioni aggiuntive.

Tipi di campo
Valore Chiave Descrizione
1 Campo di testo Input testo singola riga.
2 Area di testo Textarea multiriga.
3 Booleano Checkbox / toggle.
4 Data e/ora Selettore data e/o ora.
5 Campo numerico Input numerico con maschera.
6 Allegato Upload file.
7 Immagine Upload immagine con crop.
8 Elenco generico Dropdown / selezione multipla.
9 Lookup Lookup server-side con query configurabile.
10 Form di dettaglio Form di dettaglio annidato.
11 Elenco immagini Selettore lista immagini.
12 Etichetta Solo visualizzazione.
13 Immagine con markers Immagine con annotazioni interattive.
14 Bottone Campo pulsante azione.

English version


Overview

@eqproject/eqp-dynamic-module exposes two public components:

Component Purpose
<eqp-dynamic-module> Runtime form viewer, filler, list, filter and graphs
<eqp-dynamic-module-configurator> No-code form builder (create, edit, import, export)

Forms are defined as JSON structures stored server-side and fetched at runtime. The library handles rendering, validation, data retrieval, CRUD operations and advanced features like formulas, triggers, action buttons and speech-to-text.


Prerequisites
npm install @angular/cdk@^15.1.2 @angular/material@^15.1.2 @angular/material-luxon-adapter@^15.2.9 --legacy-peer-deps
npm install @angular-material-components/datetime-picker@^15.0.0 @angular-material-components/moment-adapter@^15.0.0 --legacy-peer-deps
npm install moment@^2.29.4 sweetalert2@^11.4.24 --legacy-peer-deps

All npm install commands for this library require --legacy-peer-deps.


Installation
npm install @eqproject/eqp-dynamic-module --legacy-peer-deps

Module Setup
import { EqpDynamicModuleModule } from '@eqproject/eqp-dynamic-module';

@NgModule({
  imports: [EqpDynamicModuleModule]
})
export class AppModule {}

Add Angular Material theme to angular.json styles:

"styles": [
  "node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
  "src/styles.css"
]

Components
eqp-dynamic-module — Form Viewer/Filler

Basic usage

import { DynamicModuleGeneralConfig, DynamicModuleViewModeEnum } from '@eqproject/eqp-dynamic-module';

generalConfig = new DynamicModuleGeneralConfig(
  'https://your-api.example.com/api',
  this.userToken,
  this.context,
  null
);
<eqp-dynamic-module
  [configurations]="generalConfig"
  [formID]="'your-form-id'"
  [starterViewMode]="DynamicModuleViewModeEnum.LIST"
  [userID]="currentUser.id"
  (saveRecord)="onSave($event)"
  (afterSaveRecord)="onAfterSave($event)">
</eqp-dynamic-module>

Inputs

Input Type Default Description
configurations DynamicModuleGeneralConfig Required. Server connection configuration.
formID string Required. ID of the form to display.
starterViewMode DynamicModuleViewModeEnum LIST Initial view mode.
userID string "0" User ID stamped on saved records.
orgaID string "0" Organization ID.
showTitle boolean true Show/hide the form name.
showBackButton boolean true Show/hide the back button.
showSaveButton boolean true Show/hide the save button.
values Record[] null Pre-loaded records for LIST mode.
FormJSON string "" Form JSON string for REPAIR mode.
formulaObject any {} Context object for formula evaluation.
selectedRecord Record | string null Pre-select a record by object or ID.
externalButtons RecordButton[] [] Extra buttons in the record action menu.
actionButtons ActionButton[] [] Action buttons for Bottone field type.
defaultListActions DynamicModuleListFormRecordActionsDefault all true Toggle default list actions.
listViewRecordTitle string[] [] Field keys composing the accordion title.
defaultListViewFunction Function null Custom function called on list load.
onSaveBackToList boolean false Return to LIST after save.
onBackTo DynamicModuleViewModeEnum null View mode for the back button.
numberOfColumns number 3 Number of layout columns.
showHiddenFields boolean true Show/hide hidden fields.
filterResultViewMode DynamicModuleFilterResultViewModeEnum INTERNAL_EQPTABLE Filter results display mode.
additionalParams any null Extra params for server filter calls.
additionalInfo any null Extra data for client-side operations.
prefilterParams any null Pre-filter parameters.
updateInfo any null Data to update response values after load.
contestualizationParams any null Contextualisation parameters.
showNewSearchButton boolean true Show/hide the new search button.
highlightFilter any Row/field highlighting configuration.
isDraggableListView boolean true Enable drag-and-drop in list view.
Statistic FilterStatistic null Statistics and filter configuration.
QueryEditorComponent any Custom query editor component for lookups.
debugMode boolean false Enable verbose console logging.

Outputs

Output Payload Description
(saveRecord) Record Emitted on save when no save endpoint is configured.
(afterSaveRecord) Record Emitted after server save call completes.
(deleteRecord) Record Emitted on delete when no delete endpoint is configured.
(afterDeleteRecord) Record Emitted after server delete call completes.
(SaveJSON) string Emitted when form JSON is exported.
(afterFilter) DynRecord[] Emitted after filter operation with result set.
(dragStarted) Record Emitted when drag starts.
(dragReleased) void Emitted when drag ends.
(clickDragIndicator) Record Emitted when drag handle is clicked.
(out) eventOut General-purpose external output.
(fireTrigger) FireTrigger Emitted when a trigger fires.
(afterOutputExternalFilters) FilterStatistic Emitted after external filters applied.

eqp-dynamic-module-configurator — Form Builder

Usage modes

<!-- Create new form -->
<eqp-dynamic-module-configurator
  *ngIf="config"
  [configurations]="config"
  (saveFormEvent)="onFormSaved($event)">
</eqp-dynamic-module-configurator>

<!-- Edit existing form -->
<eqp-dynamic-module-configurator
  [configurations]="config"
  [formID]="formID"
  (saveFormEvent)="onFormSaved($event)">
</eqp-dynamic-module-configurator>

<!-- Export form -->
<eqp-dynamic-module-configurator
  [configurations]="config"
  [formID]="formID"
  [viewMode]="'Export'"
  (saveFormEvent)="onFormSaved($event)">
</eqp-dynamic-module-configurator>

<!-- Import from JSON -->
<eqp-dynamic-module-configurator
  [configurations]="config"
  [formID]="null"
  [viewMode]="'Export'"
  (saveFormEvent)="onFormSaved($event)">
</eqp-dynamic-module-configurator>

Inputs

Input Type Default Description
configurations DynamicModuleConfiguratorConfig Required. Configuration container.
formID string null Form ID to edit. null creates a new form.
viewMode string "addOrEdit" "addOrEdit" or "Export".
fieldsExtraConfig FieldExtraConfig[] Extra configuration for specific fields.
triggers any Trigger definitions for the editor.
actionButtons any Action button definitions.
contestualization Contestualization[] Contextualisation options.
formulaObject any Context for formula preview.
QueryEditorComponent DynamicLoaderDirectiveData Custom query editor component.
debugMode boolean false Enable verbose logging.
configuratorTheme Record<string, string> | null null CSS variable overrides via TypeScript object.
configuratorThemeCss string | null null CSS variable overrides via CSS text string (e.g. contents of a .css file).

Outputs

Output Payload Description
(saveFormEvent) Form Emitted on save when no save endpoint is configured.
(afterSaveFormEvent) Form Emitted after server save call completes.
(out) eventOut General-purpose external output.
(fireTrigger) FireTrigger Emitted when a trigger fires.

Theming

The configurator exposes a theming system based on CSS custom properties. All values injected via the theme inputs are applied with !important and cannot be overridden externally except through these inputs.

<!-- Option A: TypeScript object -->
<eqp-dynamic-module-configurator
  [configurations]="config"
  [configuratorTheme]="{ '--conf-gradient': 'linear-gradient(to right, #1565c0, #0288d1)' }">
</eqp-dynamic-module-configurator>

<!-- Option B: CSS file loaded as string -->
<eqp-dynamic-module-configurator
  [configurations]="config"
  [configuratorThemeCss]="themeCssString">
</eqp-dynamic-module-configurator>

CSS file format for configuratorThemeCss (no selector required):

--conf-gradient:           linear-gradient(to right, #1565c0, #0288d1);
--conf-bg-page:            #f0f6fb;
--conf-btn-color:          #ffffff;

Available variables:

Variable Default Description
--conf-gradient purple-blue gradient Button and header background
--conf-bg-page #f5f5f5 General page/stepper background
--conf-radius 10px Button border radius
--conf-modal-radius 12px Modal border radius
--conf-accent #693DDA Accent colour (borders, focus)
--conf-primary #1E31EB Primary colour
--conf-step-selected #643cda Selected step arrow
--conf-step-edit #3034e7 Completed step arrow
--conf-stepper-header-bg inherited from --conf-bg-page Upper zone background (stepper header)
--conf-stepper-content-bg inherited from --conf-bg-page Lower zone background (form and buttons)
--conf-step-icon-edit-bg inherited from --conf-step-edit Completed step icon background
--conf-btn-color #ffffff Active button text colour (gradient background)
--conf-hint-btn-bg #2563eb Quick-suggestion button (lightbulb) background
--conf-hint-btn-hover-bg #1d4ed8 Lightbulb button hover background
--conf-table-header-bg SCSS variable Field table header background
--conf-search-bg SCSS variable Search field background
--conf-table-bg #ffffff Table row background
--conf-card-bg #ffffff Card background
--conf-font-family inherit Configurator-wide font family

Configuration Models
DynamicModuleGeneralConfig
const general = new DynamicModuleGeneralConfig(
  baseServerUrl,        // string — e.g. "https://api.example.com/api"
  userToken,            // string — auth token
  context,              // Context
  endPointConfiguration // EndPointConfiguration | null
);
DynamicModuleListFormRecordActionsDefault
const actions = new DynamicModuleListFormRecordActionsDefault();
actions.add       = true;
actions.view      = true;
actions.edit      = true;
actions.duplicate = false;
actions.delete    = true;
actions.graphs    = false;

View Modes
enum DynamicModuleViewModeEnum {
  NONE            = 0,
  VIEW            = 1,
  COMPILE         = 2,
  LIST            = 3,
  REPAIR          = 4,
  LISTWIEW        = 5,
  FILTER          = 6,
  GRAPHS          = 7,
  HLIST           = 8,
  EXTERNAL_FILTER = 9
}

Endpoint Configuration
const endPoints = new EndPointConfiguration();
endPoints.Records.SaveEndPoint = new EndPointData();
endPoints.Records.SaveEndPoint.Url = 'https://custom-api.example.com/records/save';
endPoints.Records.SaveEndPoint.RequestMethod = RequestMethodEnum.POST;
endPoints.Records.SaveEndPoint.Params = [{
  ParamName: 'orgId',
  ParamValue: this.orgaId,
  ParamType: ParamTypeEnum['Query param']
}];
const general = new DynamicModuleGeneralConfig(baseUrl, token, context, endPoints);

Available Records endpoints: GetWithContextualizationByFormCodeEndPoint, GetByFormIDEndPoint, GetByFormCodeEndPoint, GetAllByEntAndUserIDEndPoint, GetByIDEndPoint, SaveEndPoint, DuplicateEndPoint, DeleteEndPoint, RepairEndPoint, ApplyFilter, GetAllAttachmentsEndPoint.

Available Forms endpoints: GetByIDEndPoint, GetAllFormEndPoint, GetByIDAndVersionEndPoint, SaveEndPoint, SaveAttachmentEndPoint, ExportByIDEndPoint, GetAttachmentWithBases64, SpeechToFormEditEndPoint.


Data Models
Record
Property Type Description
ID string Unique record identifier.
EntID string ID of the form this record belongs to.
Version number Form version at compilation time.
userID string ID of the user who created the record.
AnswerDate string ISO date string of compilation.
HTMLreadableValues string Pre-rendered HTML of field values.
AdditionalParams any Extra parameters.
AdditionalInfo any Extra information.

Field Types Reference
Value Key Description
1 Campo di testo Single-line text input.
2 Area di testo Multi-line textarea.
3 Booleano Checkbox / boolean toggle.
4 Data e/ora Date and/or time picker.
5 Campo numerico Numeric input with mask.
6 Allegato File attachment upload.
7 Immagine Image upload with optional cropping.
8 Elenco generico Dropdown / multi-select list.
9 Lookup Server-side lookup with configurable query.
10 Form di dettaglio Embedded detail (inner) form.
11 Elenco immagini Image selector list.
12 Etichetta Display-only label.
13 Immagine con markers Image with interactive annotation markers.
14 Bottone Action button field.