dynamic-components-angular
v1.2.4
Published
Reusable configuration-driven PrimeNG dialog forms and localized inputs for Angular
Maintainers
Readme
dynamic-components-angular
Configuration-driven Angular 18 dialog forms for Nawras / Saned HR apps. Build add/edit dialogs from a field array—no duplicated p-dialog templates, validators, or PrimeNG wiring.
Peer stack: Angular 18, PrimeNG 17, @ngx-translate/core. Includes app-lookup-select (no nawras-library peer).
Install
npm install dynamic-components-angularIt gives you
<app-dynamic-dialog-form>— PrimeNG dialog + reactiveFormGroupbuilt fromGenericFormField[]<lib-localized-inputs>— multi-language name fields (Arabic, etc.) from your System Language APIGenericFormField— one strongly typed config object per field (text, dropdown, lookup, radio, checkbox, textarea, file, date, localized)- Edit / create flows —
editMode,editDatapatching,save/updateoutputs, workflow lock whenupdateWorkflowStatus === 'Submitted' - Validation — required rules per type, red asterisk on labels, translated “Required” message
- Lazy-friendly — use with
@if (visible)in parent templates
Quick start
1. App module — language API
import { LOCALIZED_LANGUAGE_ENDPOINT } from 'dynamic-components-angular';
import { getBaseUrl } from './environments/environment';
providers: [
{
provide: LOCALIZED_LANGUAGE_ENDPOINT,
useFactory: () =>
getBaseUrl() + '/api/0/SharedData/SystemLanguage/v1/all',
},
]Optional — bind app LanguageService on the parent component:
import { LanguageService } from 'dynamic-components-angular';
import { LanguageService as AppLanguageService } from './shared/localized-inputs/language.service';
providers: [{ provide: LanguageService, useExisting: AppLanguageService }]2. Standalone parent component
Template (new-department.component.html):
@if (visible) {
<app-dynamic-dialog-form
[visible]="visible"
(visibleChange)="visible = $event"
[editMode]="editMode"
[editData]="editData"
[fields]="fields"
[customFieldsConfig]="customFieldsConfig"
dialogTitle="Department"
dialogWidth="50vw"
(save)="onSave($event)"
(update)="onUpdate($event)"
(closeDialog)="visible = false"
/>
}Component (new-department.component.ts):
import {
DynamicDialogFormComponent,
GenericFormField,
GenericFormValue,
GenericFormCustomFieldsConfig,
} from 'dynamic-components-angular';
@Component({
standalone: true,
imports: [DynamicDialogFormComponent],
templateUrl: './new-department.component.html',
})
export class NewDepartmentComponent {
visible = false;
editMode = false;
editData = null;
customFieldsConfig = {
labelPrefix: 'DepartmentName',
columnClass: 'col-12 md:col-4',
excludeLangNames: ['English'],
placeholder: 'Enter name in',
};
fields = [
{ name: 'code', label: 'DepartmentCode', type: 'text', required: true },
{ name: 'name', label: 'DepartmentName', type: 'text', required: true },
{ name: 'description', label: 'SecondDescription', type: 'textarea', required: true, rows: 3 },
];
onSave(value) { /* API create */ }
onUpdate(value) { /* API update */ }
}npm readme tip: Examples use
html/js/jsonfences so code stays readable in npm dark mode. Avoid largetypescriptblocks with inline templates.
Supported field types
| type | Control | Notes |
|--------|---------|--------|
| text | pInputText | numericOnly, placeholder |
| number | pInputText | Same as text with number input mode |
| dropdown | p-dropdown | options, optionLabel, optionValue, filter/clear |
| date | p-calendar | dateFormat, showTime |
| lookup | app-lookup-select | Server-side lookup API; see lookup config below |
| radio | p-radioButton | options, radioLayout |
| checkbox | p-checkbox | binary (default true), checkboxLabel |
| textarea | pInputTextarea | rows, autoResize |
| file | p-fileUpload (basic) | accept, multiple, maxFileSize; value is File or File[] |
| localized | via customFieldsConfig | Multi-language map on customFields control |
GenericFormField properties
Each item in [fields] is a GenericFormField (alias: DynamicDialogFormFieldConfig).
| Property | Type | Used for |
|----------|------|----------|
| name | string | Form control name |
| label | string | Label (translate key) |
| type | GenericFormFieldType | Field renderer |
| required | boolean | Validation + red * |
| columnClass | string | PrimeFlex column, e.g. col-12 md:col-4 |
| placeholder | string | Input placeholder |
| disabled | boolean | Disable control |
| defaultValue | unknown | Create-mode default |
| editKey | string | Patch from editData[editKey] |
| numericOnly | boolean | Text/number: digits only |
| options | array | Dropdown / radio options |
| optionLabel / optionValue | string | Option binding keys |
| filter, showClear, filterBy | — | Dropdown filter |
| entity, module, version | string | Lookup API |
| lookupType | string | id-name | text | id | name |
| appendTo, styleClass | string | Lookup UI |
| sReadOnly, getAll | boolean | Lookup behaviour |
| functionName, query | — | Custom lookup endpoint |
| selectFirstOnLoad, searchDebounce | — | Lookup load/search |
| radioLayout | string | horizontal | vertical |
| binary, checkboxLabel | — | Checkbox |
| rows, autoResize | — | Textarea |
| accept, multiple, maxFileSize, chooseLabel | — | File upload |
| dateFormat, showTime | — | Calendar |
Example configurations
Text
{
"name": "code",
"label": "DepartmentCode",
"type": "text",
"required": true,
"numericOnly": true,
"columnClass": "col-12 md:col-4",
"placeholder": "Enter code"
}Dropdown
{
"name": "divisionId",
"label": "Parent Division",
"type": "dropdown",
"columnClass": "col-12 md:col-4",
"optionLabel": "label",
"optionValue": "value",
"filter": true,
"showClear": true,
"filterBy": "label"
}Lookup (app-lookup-select)
{
"name": "managerId",
"label": "DepartmentManager",
"type": "lookup",
"required": true,
"columnClass": "col-12 md:col-4",
"entity": "Employees",
"module": "SanedHR",
"version": "v1",
"lookupType": "id-name",
"optionLabel": "text",
"optionValue": "id",
"appendTo": "body",
"placeholder": "Select manager",
"sReadOnly": false,
"getAll": false,
"query": {},
"selectFirstOnLoad": false,
"searchDebounce": 400
}Radio
{
"name": "status",
"label": "Status",
"type": "radio",
"required": true,
"radioLayout": "horizontal",
"optionLabel": "label",
"optionValue": "value",
"options": [
{ "label": "Active", "value": "active" },
{ "label": "Inactive", "value": "inactive" }
]
}Checkbox
{
"name": "isPrimary",
"label": "PrimaryDepartment",
"type": "checkbox",
"binary": true,
"checkboxLabel": "Mark as primary",
"defaultValue": false,
"columnClass": "col-12 md:col-4"
}Textarea
{
"name": "description",
"label": "SecondDescription",
"type": "textarea",
"required": true,
"rows": 4,
"autoResize": true,
"columnClass": "col-12"
}File upload
{
"name": "attachment",
"label": "Attachment",
"type": "file",
"accept": ".pdf,.doc,.docx",
"multiple": false,
"maxFileSize": 5000000,
"chooseLabel": "Choose file",
"columnClass": "col-12 md:col-6"
}On submit, form.getRawValue() includes attachment as a File (or File[] when multiple: true).
app-dynamic-dialog-form API
Inputs
| Input | Description |
|-------|-------------|
| visible | Show/hide dialog (two-way with visibleChange) |
| editMode | false = Save, true = Update |
| editData | Row object to patch in edit mode |
| fields | GenericFormField[] |
| dialogTitle | Header title (translate key) |
| dialogWidth | CSS width, e.g. '50vw' |
| customFieldsConfig | Localized inputs block (lib-localized-inputs) |
| newRecordDefaults | Default values when creating |
| updateWorkflowStatus | 'Submitted' disables the form |
Outputs
| Output | Description |
|--------|-------------|
| save | Emits form value on create |
| update | Emits form value on edit |
| closeDialog | User closed dialog |
| visibleChange | Dialog visibility changed |
Public exports
DynamicDialogFormComponent
DynamicDialogFormModule
GenericFormField
GenericFormFieldType
GenericFormValue
GenericFormCustomFieldsConfig
GENERIC_FORM_FIELD_EXAMPLES
SAMPLE_GENERIC_FORM_FIELDS
LocalizedInputsModule
LocalizedInputsComponent
LanguageService
LOCALIZED_LANGUAGE_ENDPOINTImport from package name: dynamic-components-angular
Peer dependencies
| Package | Purpose |
|---------|---------|
| @angular/core ^18.2 | Framework |
| @angular/forms ^18.2 | Reactive forms |
| primeng 17.18 | Dialog, inputs, file upload, etc. |
| @ngx-translate/core ^15 | Labels and validation messages |
| rxjs ~7.8 | — |
Host apps must provide HttpClientModule (or provideHttpClient()) so lookups can call your Nawras API. Lookup URLs follow the same tenant/subdomain rules as nawras-library.
For maintainers
Build and pack from this workspace root:
npm run release-dynamic-componentsPublish to npm (after npm login):
npm run publish-dynamic-componentsDo not run npm publish dist/dynamic-components — npm may treat that path as a git URL.
Local .tgz install:
"dynamic-components-angular": "file:dynamic-components-angular-1.1.6.tgz"License
UNLICENSED — internal / Obeikan Nawras use unless otherwise specified.
