@ngx-json-forms/primeng 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +159 -0
- package/fesm2022/ngx-json-forms-primeng.mjs +650 -0
- package/fesm2022/ngx-json-forms-primeng.mjs.map +1 -0
- package/package.json +45 -0
- package/types/ngx-json-forms-primeng.d.ts +106 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngx-json-forms-primeng.mjs","sources":["../../../../packages/primeng/src/lib/ngx-form-engine-primeng.component.ts","../../../../packages/primeng/src/lib/ngx-form-engine-primeng.component.html","../../../../packages/primeng/src/lib/ngx-json-form-stepper.component.ts","../../../../packages/primeng/src/ngx-json-forms-primeng.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n Type,\n} from '@angular/core';\nimport { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport { NgComponentOutlet, NgOptimizedImage, NgTemplateOutlet } from '@angular/common';\nimport { Subscription } from 'rxjs';\n\nimport { InputTextModule } from 'primeng/inputtext';\nimport { InputGroupModule } from 'primeng/inputgroup';\nimport { InputGroupAddonModule } from 'primeng/inputgroupaddon';\nimport { FloatLabelModule } from 'primeng/floatlabel';\nimport { SelectModule } from 'primeng/select';\nimport { MultiSelectModule } from 'primeng/multiselect';\nimport { CascadeSelectModule } from 'primeng/cascadeselect';\nimport { AutoCompleteModule } from 'primeng/autocomplete';\nimport { FileUploadModule } from 'primeng/fileupload';\nimport { ButtonModule } from 'primeng/button';\nimport { DialogModule } from 'primeng/dialog';\nimport { DividerModule } from 'primeng/divider';\nimport { PasswordModule } from 'primeng/password';\nimport { DatePickerModule } from 'primeng/datepicker';\nimport { CheckboxModule } from 'primeng/checkbox';\nimport { ToggleSwitchModule } from 'primeng/toggleswitch';\nimport { TextareaModule } from 'primeng/textarea';\nimport { SliderModule } from 'primeng/slider';\nimport { RatingModule } from 'primeng/rating';\nimport { ColorPickerModule } from 'primeng/colorpicker';\nimport { RadioButtonModule } from 'primeng/radiobutton';\nimport { KeyFilterModule } from 'primeng/keyfilter';\nimport { EditorModule } from 'primeng/editor';\n\nimport {\n FieldRegistry,\n FormEngineEvent,\n FormEngineEventType,\n FormEngineService,\n FormField,\n FormSchema,\n ImageUploadService,\n} from '@ngx-json-forms/core';\n\n@Component({\n selector: 'ngx-json-form',\n templateUrl: './ngx-form-engine-primeng.component.html',\n styleUrl: './ngx-form-engine-primeng.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ReactiveFormsModule,\n NgTemplateOutlet,\n NgComponentOutlet,\n NgOptimizedImage,\n // PrimeNG\n InputTextModule,\n InputGroupModule,\n InputGroupAddonModule,\n FloatLabelModule,\n SelectModule,\n MultiSelectModule,\n CascadeSelectModule,\n AutoCompleteModule,\n FileUploadModule,\n ButtonModule,\n DialogModule,\n DividerModule,\n PasswordModule,\n DatePickerModule,\n CheckboxModule,\n ToggleSwitchModule,\n TextareaModule,\n SliderModule,\n RatingModule,\n ColorPickerModule,\n RadioButtonModule,\n KeyFilterModule,\n EditorModule,\n ],\n})\nexport class NgxJsonFormComponent {\n // ─── Inputs / Outputs ────────────────────────────────────────────────────\n\n readonly formTitle = input<string>('');\n readonly fieldsInput = input<FormField[]>([]);\n /** Optional schema input — supersedes `fieldsInput` when provided. */\n readonly schema = input<FormSchema | null>(null);\n /** Only render fields in the given step indices (used by the stepper wrapper). */\n readonly stepFields = input<FormField[] | null>(null);\n\n readonly formSubmit = output<FormEngineEvent>();\n readonly formChange = output<FormEngineEvent>();\n\n // ─── Services ────────────────────────────────────────────────────────────\n\n protected readonly formService = inject(FormEngineService);\n protected readonly uploadService = inject(ImageUploadService);\n protected readonly fieldRegistry = inject(FieldRegistry);\n\n // ─── Internal State ──────────────────────────────────────────────────────\n\n readonly fields = signal<FormField[]>([]);\n readonly formGroup = signal<FormGroup>(new FormGroup({}));\n readonly ready = signal(false);\n\n /** Async-loaded options keyed by formControlName */\n readonly asyncOptions = signal<Record<string, unknown[]>>({});\n\n private readonly formStatusTick = signal(0);\n private readonly focusedMap = signal<Record<string, boolean>>({});\n\n /** Subscriptions for async option re-loads; disposed on every rebuild. */\n private optionLoaderSubs: Subscription[] = [];\n\n // ─── Derived ─────────────────────────────────────────────────────────────\n\n readonly visibleFields = computed(() => {\n this.formStatusTick();\n this.formService.patchTick();\n const values = this.formGroup().getRawValue();\n const source = this.stepFields() ?? this.fields();\n return source.filter((f) => {\n if (f.config.attributes.visible === false) return false;\n return this.formService.evaluateShowWhen(f, values);\n });\n });\n\n /**\n * Track patchTick so .valid (a plain object property) re-reads after every\n * form change. Without this, the submit-button disabled binding stays stuck\n * on the FormGroup's initial (invalid) state.\n */\n readonly formValid = computed(() => {\n this.formService.patchTick();\n this.formStatusTick();\n return this.formGroup().valid;\n });\n\n protected placeholderVisibilityMap: Record<string, ReturnType<typeof computed>> = {};\n\n /**\n * Resolve the placeholder string to render for a field. Safe for nested\n * fields (repeater itemFields, group groupFields) whose formControlName\n * isn't pre-registered in `placeholderVisibilityMap` — those fall back to\n * the raw `field.placeholder` since they don't participate in floatLabel.\n */\n protected placeholderFor(field: FormField): string | null {\n const name = field.formControlName;\n if (!name) return field.placeholder ?? null;\n const sig = this.placeholderVisibilityMap[name];\n if (!sig) return field.placeholder ?? null;\n return sig() ? (field.placeholder ?? null) : null;\n }\n\n readonly errorMap = computed(() => {\n this.formStatusTick();\n this.formService.patchTick();\n const errors: Record<string, string | null> = {};\n const group = this.formGroup();\n if (!group) return errors;\n for (const field of this.fields()) {\n if (!field.formControlName) continue;\n const control = group.get(field.formControlName);\n errors[field.formControlName] = this.formService.resolveError(field, control);\n }\n return errors;\n });\n\n // ─── Lifecycle ───────────────────────────────────────────────────────────\n\n constructor() {\n effect(() => {\n this.ready.set(false);\n\n const schemaIn = this.schema();\n const incoming: FormField[] = schemaIn?.fields\n ? schemaIn.fields\n : schemaIn?.steps\n ? schemaIn.steps.flatMap((s) => s.fields)\n : this.fieldsInput();\n\n if (!incoming.length) return;\n\n const sorted = [...incoming].sort((a, b) => {\n const oa = a.layout?.order ?? Number.MAX_SAFE_INTEGER;\n const ob = b.layout?.order ?? Number.MAX_SAFE_INTEGER;\n return oa - ob;\n });\n\n this.fields.set(sorted);\n this.buildForm(sorted, schemaIn ?? undefined);\n });\n\n effect(() => {\n this.formService.patchTick();\n if (!this.ready()) return;\n this.fields.set(this.formService.fields());\n this.uploadService.syncPreviews(this.fields(), this.formGroup());\n });\n }\n\n // ─── Form Builder ────────────────────────────────────────────────────────\n\n private buildForm(fields: FormField[], schema?: FormSchema): void {\n // Tear down anything tied to the previous form group before we rebuild.\n this.disposeOptionLoaderSubs();\n this.placeholderVisibilityMap = {};\n\n const group = this.formService.buildFormGroup(fields);\n this.formGroup.set(group);\n\n // Register synchronously so prior subs are disposed BEFORE we add new\n // computed-field listeners below — otherwise register() would wipe them.\n this.formService.register(group, fields, schema);\n\n for (const field of fields) {\n if (!field.formControlName) continue;\n this.placeholderVisibilityMap[field.formControlName] = computed(() => {\n if (!field.floatLabel) return true;\n const control = this.formGroup()?.get(field.formControlName!);\n if (!control) return false;\n const v = control.value;\n const hasValue =\n v !== null && v !== undefined && v !== '' && (!Array.isArray(v) || v.length > 0);\n return this.focusedMap()[field.formControlName!] === true && !hasValue;\n });\n }\n\n if (schema?.crossFieldValidators?.length) {\n this.formService.applyCrossFieldValidators(group, schema.crossFieldValidators);\n }\n this.formService.setupComputedFields(group, fields);\n\n // Bootstrap async options for select-like fields\n for (const f of fields) {\n const a = f.config.attributes;\n if (a.optionsLoader && f.formControlName) {\n void this.loadAsyncOptions(f);\n for (const dep of a.optionsDependsOn ?? []) {\n const depCtrl = group.get(dep);\n if (!depCtrl) continue;\n this.optionLoaderSubs.push(\n depCtrl.valueChanges.subscribe(() => void this.loadAsyncOptions(f))\n );\n }\n }\n }\n\n queueMicrotask(() => {\n this.ready.set(true);\n this.uploadService.syncPreviews(this.fields(), this.formGroup());\n });\n }\n\n private disposeOptionLoaderSubs(): void {\n for (const s of this.optionLoaderSubs) s.unsubscribe();\n this.optionLoaderSubs = [];\n }\n\n private async loadAsyncOptions(field: FormField): Promise<void> {\n const a = field.config.attributes;\n if (!a.optionsLoader || !field.formControlName) return;\n const formValue = this.formGroup().getRawValue();\n const context: Record<string, unknown> = {};\n for (const dep of a.optionsDependsOn ?? []) context[dep] = formValue[dep];\n\n this.formService.updateFieldAttributes(field.formControlName, { loading: true });\n const opts = await this.formService.resolveDependentOptions(a.optionsLoader, context, formValue);\n this.asyncOptions.update((m) => ({ ...m, [field.formControlName!]: opts }));\n this.formService.updateFieldAttributes(field.formControlName, { loading: false, options: opts });\n }\n\n // ─── Field Registry resolver (used by custom inputType) ──────────────────\n\n protected customRenderer(field: FormField): Type<unknown> | undefined {\n return this.fieldRegistry.getRenderer(field.config.attributes.inputType);\n }\n\n protected customRendererInputs(field: FormField): Record<string, unknown> {\n return { field, formGroup: this.formGroup() };\n }\n\n // ─── Date helpers ────────────────────────────────────────────────────────\n\n protected minDateFor(field: FormField): Date | undefined {\n const a = field.config.attributes;\n if (a.minDate) return a.minDate;\n if (a.minToday) {\n const d = new Date();\n d.setDate(d.getDate() + (a.minOffsetDays ?? 0));\n return d;\n }\n return undefined;\n }\n\n protected maxDateFor(field: FormField): Date | undefined {\n const a = field.config.attributes;\n if (a.maxDate) return a.maxDate;\n if (a.maxToday) {\n const d = new Date();\n d.setDate(d.getDate() + (a.maxOffsetDays ?? 0));\n return d;\n }\n return undefined;\n }\n\n // ─── Effective options resolver ──────────────────────────────────────────\n\n protected optionsFor(field: FormField): unknown[] {\n const a = field.config.attributes;\n if (field.formControlName && this.asyncOptions()[field.formControlName]) {\n return this.asyncOptions()[field.formControlName];\n }\n return (a.options as unknown[]) ?? [];\n }\n\n // ─── Repeater helpers ────────────────────────────────────────────────────\n\n protected getArray(name: string): FormArray | null {\n const c = this.formGroup().get(name);\n return c instanceof FormArray ? c : null;\n }\n\n protected addRepeaterRow(field: FormField): void {\n if (!field.formControlName) return;\n const arr = this.getArray(field.formControlName);\n if (!arr) return;\n if (field.config.attributes.maxRows && arr.length >= field.config.attributes.maxRows) return;\n this.formService.addArrayItem(field.formControlName);\n this.triggerTick();\n }\n\n protected removeRepeaterRow(field: FormField, i: number): void {\n if (!field.formControlName) return;\n const arr = this.getArray(field.formControlName);\n if (!arr) return;\n if (field.config.attributes.minRows && arr.length <= field.config.attributes.minRows) return;\n this.formService.removeArrayItem(field.formControlName, i);\n this.triggerTick();\n }\n\n protected rowGroup(field: FormField, i: number): FormGroup {\n return this.getArray(field.formControlName!)?.at(i) as FormGroup;\n }\n\n /**\n * DOM id for a field's input element. Scoped by row index when the field\n * lives inside a repeater so the same `formControlName` across rows\n * doesn't produce duplicate ids (HTML spec violation + breaks\n * <label for>, aria-describedby, and document.querySelector lookups).\n */\n protected inputId(field: FormField, suffix?: number | string): string {\n const base = (field.formControlName ?? '') + 'Id';\n return suffix !== undefined && suffix !== null ? `${base}_${suffix}` : base;\n }\n\n /**\n * Resolve the validation message for a single field inside a repeater row.\n * Mirrors errorMap() but for FormGroup rows that aren't tracked in the\n * top-level fields signal.\n */\n protected resolveRowError(row: FormGroup, sub: FormField): string | null {\n this.formService.patchTick();\n if (!sub.formControlName) return null;\n const ctrl = row.get(sub.formControlName);\n return this.formService.resolveError(sub, ctrl);\n }\n\n // ─── Events ──────────────────────────────────────────────────────────────\n\n /** Central event handler. Accepts `unknown` because PrimeNG emits custom event objects. */\n async onEvent(field: FormField, event: unknown, eventType?: FormEngineEventType): Promise<void> {\n this.triggerTick();\n\n const rawType = eventType ?? ((event as Event)?.type as FormEngineEventType);\n let type = rawType;\n\n if (type === 'focus')\n this.focusedMap.update((m) => ({ ...m, [field.formControlName!]: true }));\n if (type === 'blur')\n this.focusedMap.update((m) => ({ ...m, [field.formControlName!]: false }));\n\n if (type === 'uploadHandler') {\n await this.uploadService.handleUpload(\n field,\n event as { files: File[] },\n this.formGroup(),\n this.formService,\n () => this.emitChange(field, 'uploadHandler', event)\n );\n return;\n }\n\n if (type === 'inputKeydown' && field.config.attributes.inputType === 'autocomplete') {\n const ke = event as KeyboardEvent;\n if (ke.key === 'Enter') {\n const inputValue = (ke.target as HTMLInputElement).value?.trim();\n if (inputValue) {\n const tag = {\n [field.config.attributes.optionLabel!]: inputValue,\n [field.config.attributes.optionValue!]: inputValue,\n };\n const existing = [...((field.config.attributes.suggestions as unknown[]) ?? []), tag];\n this.formService.updateFieldAttributes(field.formControlName!, { suggestions: existing });\n this.formGroup().get(field.formControlName!)?.setValue(existing);\n type = 'add';\n }\n }\n }\n\n if (type === 'unselect' && field.config.attributes.inputType === 'autocomplete') {\n const evtValue = (event as { value: unknown }).value;\n const remaining = ((field.config.attributes.suggestions as unknown[]) ?? []).filter(\n (v) => evtValue !== v\n );\n this.formService.updateFieldAttributes(field.formControlName!, { suggestions: remaining });\n this.formGroup().get(field.formControlName!)?.setValue(remaining);\n }\n\n const allowed = field.config.attributes.acceptedEvents ?? [];\n if (!allowed.includes(type)) return;\n\n const payload = this.buildPayload(field, type, event);\n\n if (type === 'click') {\n const role = field.config.attributes.buttonRole;\n if (role === 'reset') {\n this.formService.reset();\n this.formChange.emit(payload);\n return;\n }\n if (role === 'cancel' || role === 'custom') {\n this.formChange.emit(payload);\n return;\n }\n if (!this.formValid()) this.formGroup().markAllAsTouched();\n this.formSubmit.emit({ ...payload, values: this.formService.buildSubmitPayload() });\n } else {\n this.formChange.emit(payload);\n }\n }\n\n removeImage(field: FormField, image: string): void {\n this.uploadService.removeImage(\n field,\n image,\n this.formGroup(),\n this.formService,\n () => this.emitChange(field, 'uploadHandler', new Event('remove'))\n );\n }\n\n // ─── Helpers ─────────────────────────────────────────────────────────────\n\n private buildPayload(field: FormField, type: FormEngineEventType, originalEvent: unknown): FormEngineEvent {\n return {\n field,\n values: this.formGroup().getRawValue(),\n valid: this.formValid(),\n type,\n originalEvent,\n };\n }\n\n private emitChange(field: FormField, type: FormEngineEventType, event: unknown): void {\n this.formChange.emit(this.buildPayload(field, type, event));\n }\n\n private triggerTick(): void {\n this.formStatusTick.update((v) => v + 1);\n }\n\n protected getControl(name: string): FormControl {\n return this.formGroup().get(name) as FormControl;\n }\n}\n","@if (formTitle().length) {\n <div class=\"ngx-form-title\">{{ formTitle() }}</div>\n}\n\n@if (ready()) {\n <form [formGroup]=\"formGroup()\" class=\"ngx-form-grid\">\n @for (field of visibleFields(); track field.formControlName ?? $index) {\n <div\n [class]=\"\n 'ngx-col-' +\n (field.layout?.columnSpan ?? 12) +\n ' ' +\n (field.layout?.wrapperClass ?? '')\n \"\n [style]=\"field.layout?.wrapperStyle ?? {}\"\n [style.display]=\"field.config.attributes.isHidden ? 'none' : 'block'\"\n >\n <!-- Float Label wrapper -->\n @if (field.floatLabel) {\n <p-floatlabel [variant]=\"field.floatVariant ?? 'on'\">\n <div class=\"ngx-field-inner\">\n <ng-container\n [ngTemplateOutlet]=\"fieldTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: field, formGroup: formGroup() }\"\n />\n </div>\n <label\n [attr.for]=\"field.formControlName + 'Id'\"\n [attr.id]=\"field.formControlName + 'Label'\"\n >\n @if (field.labelIconPos === 'left') {\n <i [class]=\"field.labelIcon\"></i>\n }\n {{ field.label }}\n @if (field.labelIconPos === 'right') {\n <i [class]=\"field.labelIcon\"></i>\n }\n @if (field.validations?.rules?.required) {\n <span class=\"ngx-required\">*</span>\n }\n </label>\n </p-floatlabel>\n }\n\n <!-- Toggle card layout -->\n @else if (\n field.config.attributes.cardLayout &&\n field.config.attributes.inputType === 'toggle'\n ) {\n <div\n class=\"ngx-toggle-card\"\n [style.--toggle-color]=\"field.config.attributes.cardIconColor\"\n >\n <div\n class=\"ngx-toggle-card-icon\"\n [style.background]=\"\n field.config.attributes.cardIconBg ??\n 'var(--p-primary-50, #eff6ff)'\n \"\n [style.color]=\"\n field.config.attributes.cardIconColor ??\n 'var(--p-primary-500, #3b82f6)'\n \"\n >\n <i [class]=\"field.config.attributes.cardIcon ?? 'pi pi-bell'\"></i>\n </div>\n <div class=\"ngx-toggle-card-body\">\n <span class=\"ngx-toggle-card-label\">\n {{ field.label }}\n @if (field.validations?.rules?.required) {\n <span class=\"ngx-required\">*</span>\n }\n </span>\n @if (field.config.attributes.info?.length) {\n <span\n class=\"ngx-toggle-card-desc\"\n [innerHTML]=\"field.config.attributes.info\"\n ></span>\n }\n </div>\n <p-toggleswitch\n [formControlName]=\"field.formControlName!\"\n [inputId]=\"field.formControlName + 'Id'\"\n (onChange)=\"onEvent(field, $event, 'change')\"\n />\n </div>\n <!--\n Always reserve one line of space for the error so the row height\n doesn't change when validation fires (otherwise sibling fields\n jump down when the error appears).\n -->\n @if (field.validations?.rules) {\n <small\n class=\"ngx-error\"\n [class.ngx-error--placeholder]=\"!errorMap()[field.formControlName!]\"\n [attr.id]=\"field.formControlName + 'Err'\"\n >{{ errorMap()[field.formControlName!] || ' ' }}</small>\n }\n }\n\n <!-- Normal label wrapper -->\n @else {\n @if (field.label && field.label.length) {\n <label\n class=\"ngx-field-label\"\n [attr.for]=\"field.formControlName + 'Id'\"\n [attr.id]=\"field.formControlName + 'Label'\"\n >\n @if (field.labelIconPos === 'left') {\n <i [class]=\"field.labelIcon\"></i>\n }\n {{ field.label }}\n @if (field.labelIconPos === 'right') {\n <i [class]=\"field.labelIcon\"></i>\n }\n @if (field.validations?.rules?.required) {\n <span class=\"ngx-required\">*</span>\n }\n </label>\n }\n <div class=\"ngx-field-inner\">\n <ng-container\n [ngTemplateOutlet]=\"fieldTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: field, formGroup: formGroup() }\"\n />\n </div>\n\n <!--\n Validation error — always reserve one line of space (placeholder\n class makes it invisible when there's no error) so triggering a\n required/pattern message doesn't push the row below it down.\n -->\n @if (field.validations?.rules) {\n <small\n class=\"ngx-error\"\n [class.ngx-error--placeholder]=\"!errorMap()[field.formControlName!]\"\n [attr.id]=\"field.formControlName + 'Err'\"\n >{{ errorMap()[field.formControlName!] || ' ' }}</small>\n }\n\n <!-- Info / hint -->\n @if (field.config.attributes.info?.length) {\n <small\n class=\"ngx-hint\"\n [attr.id]=\"field.formControlName + 'Hint'\"\n [innerHTML]=\"field.config.attributes.info\"\n ></small>\n }\n }\n </div>\n }\n </form>\n}\n\n<!-- ─── Field Renderer Template ──────────────────────────────────────────── -->\n<!--\n `formGroup` is passed in via the template context so each rendering site\n binds the right group: the root FormGroup for top-level fields, the row's\n FormGroup for repeater rows. Hard-coding `formGroup()` here would override\n row-level bindings and route nested formControlName lookups to the root,\n which is the bug we're fixing.\n\n Known issue: during initial CD passes Angular logs NG01050 spam because\n the FormGroup directive on this ng-container materialises after children\n formControlName directives query their parent ControlContainer. Bindings\n recover and form values flow correctly afterwards. Cleaner fix would be\n to avoid the ngTemplateOutlet + context + nested formGroup combination\n altogether (e.g. inline the @switch at each call site).\n-->\n<ng-template #fieldTpl let-field let-fg=\"formGroup\" let-idSuffix=\"idSuffix\">\n <ng-container [formGroup]=\"fg\">\n @switch (field.config.attributes.inputType) {\n <!-- ── Custom field (registry) ── -->\n @case (customRenderer(field) ? field.config.attributes.inputType : '__never__') {\n <ng-container\n *ngComponentOutlet=\"customRenderer(field)!; inputs: customRendererInputs(field)\"\n />\n }\n\n <!-- ── Group (nested FormGroup) ── -->\n @case ('group') {\n <fieldset\n class=\"ngx-field-group\"\n [attr.formGroupName]=\"field.formControlName\"\n >\n @for (sub of field.config.attributes.groupFields ?? []; track sub.formControlName ?? $index) {\n <div class=\"ngx-field-group-row\">\n <ng-container\n [ngTemplateOutlet]=\"fieldTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: sub, formGroup: formGroup() }\"\n />\n </div>\n }\n </fieldset>\n }\n\n <!-- ── Repeater (FormArray) ── -->\n @case ('repeater') {\n <div class=\"ngx-repeater\">\n @for (row of getArray(field.formControlName!)?.controls ?? []; track $index) {\n @let rowIndex = $index;\n <div class=\"ngx-repeater-row\" [formGroup]=\"$any(row)\">\n <div class=\"ngx-repeater-row-fields\">\n @for (sub of field.config.attributes.itemFields ?? []; track sub.formControlName ?? $index) {\n <div\n [class]=\"\n 'ngx-col-' + (sub.layout?.columnSpan ?? 12)\n \"\n >\n @if (sub.label) {\n <label\n class=\"ngx-field-label\"\n [attr.for]=\"inputId(sub, rowIndex)\"\n >\n {{ sub.label }}\n @if (sub.validations?.rules?.required) {\n <span class=\"ngx-required\">*</span>\n }\n </label>\n }\n <ng-container\n [ngTemplateOutlet]=\"fieldTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: sub, formGroup: $any(row), idSuffix: rowIndex }\"\n />\n @if (sub.validations?.rules && sub.formControlName) {\n <small\n class=\"ngx-error\"\n [class.ngx-error--placeholder]=\"!resolveRowError($any(row), sub)\"\n >{{ resolveRowError($any(row), sub) || ' ' }}</small>\n }\n </div>\n }\n </div>\n <button\n type=\"button\"\n class=\"ngx-repeater-remove\"\n pButton\n [icon]=\"'pi pi-trash'\"\n [rounded]=\"true\"\n [text]=\"true\"\n (click)=\"removeRepeaterRow(field, $index)\"\n ></button>\n </div>\n }\n <button\n pButton\n type=\"button\"\n class=\"ngx-repeater-add\"\n [icon]=\"'pi pi-plus'\"\n [label]=\"field.config.attributes.addLabel ?? 'Add row'\"\n [text]=\"true\"\n (click)=\"addRepeaterRow(field)\"\n ></button>\n </div>\n }\n\n <!-- ── Dependent / Cascading Dropdown ── -->\n @case ('dependentDropdown') {\n <p-cascadeselect\n [id]=\"inputId(field, idSuffix)\"\n [inputId]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [options]=\"$any(optionsFor(field))\"\n [optionLabel]=\"field.config.attributes.optionLabel ?? 'label'\"\n [optionValue]=\"field.config.attributes.optionValue ?? 'value'\"\n [optionGroupLabel]=\"field.config.attributes.optionGroupLabel ?? 'label'\"\n [optionGroupChildren]=\"\n $any(field.config.attributes.optionGroupChildren ?? ['children'])\n \"\n [placeholder]=\"field.placeholder ?? ''\"\n appendTo=\"body\"\n (onChange)=\"onEvent(field, $event, 'change')\"\n (onShow)=\"onEvent(field, $event, 'show')\"\n (onHide)=\"onEvent(field, $event, 'hide')\"\n />\n }\n\n <!-- ── Editor (rich text) ── -->\n @case ('editor') {\n <p-editor\n [formControlName]=\"field.formControlName!\"\n [style]=\"{ height: (field.config.attributes['height'] ?? '180px') }\"\n (onTextChange)=\"onEvent(field, $event, 'change')\"\n ></p-editor>\n }\n\n <!-- ── Confirm password ── -->\n @case ('confirmPassword') {\n <p-password\n [inputId]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [feedback]=\"false\"\n [toggleMask]=\"field.config.attributes.toggleMask ?? true\"\n [placeholder]=\"field.placeholder ?? ''\"\n appendTo=\"body\"\n (onBlur)=\"onEvent(field, $event, 'blur')\"\n />\n }\n\n <!-- ── File Upload ── -->\n @case ('fileUpload') {\n <div>\n <div\n [class]=\"field.config.attributes.isInline ? 'ngx-file-inline' : ''\"\n >\n <p-fileUpload\n mode=\"basic\"\n customUpload\n [id]=\"inputId(field, idSuffix)\"\n [multiple]=\"field.config.attributes.multiple\"\n [chooseIcon]=\"field.config.attributes.chooseIcon ?? 'pi pi-upload'\"\n [accept]=\"field.config.attributes.accept ?? 'image/*'\"\n [maxFileSize]=\"field.config.attributes.maxFileSize ?? 1000000\"\n [auto]=\"true\"\n [chooseLabel]=\"field.config.attributes.chooseLabel ?? 'Upload'\"\n (uploadHandler)=\"onEvent(field, $event, 'uploadHandler')\"\n />\n\n @if (uploadService.imagePreviews()[field.formControlName!]?.length) {\n <div class=\"ngx-image-list\">\n @for (\n image of uploadService.imagePreviews()[field.formControlName!];\n let i = $index;\n track i\n ) {\n <div class=\"ngx-image-card\">\n <i\n class=\"pi pi-times ngx-image-remove\"\n (click)=\"removeImage(field, image)\"\n ></i>\n <div class=\"ngx-image-wrapper\">\n @if (!uploadService.isBase64(image)) {\n <img\n fill\n sizes=\"100\"\n [ngSrc]=\"image\"\n (load)=\"uploadService.onLoad(image)\"\n (error)=\"uploadService.onLoad(image)\"\n [class.loading]=\"uploadService.isLoading(image)\"\n [class.loaded]=\"!uploadService.isLoading(image)\"\n class=\"ngx-preview-img\"\n alt=\"preview\"\n />\n } @else {\n <img\n fill\n sizes=\"100\"\n [src]=\"image\"\n (load)=\"uploadService.onLoad(image)\"\n (error)=\"uploadService.onLoad(image)\"\n [class.loading]=\"uploadService.isLoading(image)\"\n [class.loaded]=\"!uploadService.isLoading(image)\"\n class=\"ngx-preview-img\"\n alt=\"preview\"\n />\n }\n @if (uploadService.isLoading(image)) {\n <div class=\"ngx-img-skeleton\"></div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n\n <!-- ── Static Text ── -->\n @case ('staticText') {\n <span\n (click)=\"onEvent(field, $event, 'staticTextClick')\"\n [innerHTML]=\"field.config.attributes.value\"\n ></span>\n }\n\n <!-- ── Divider ── -->\n @case ('divider') {\n <p-divider\n [layout]=\"field.config.attributes.dividerLayout\"\n [type]=\"field.config.attributes.dividerType\"\n [align]=\"field.config.attributes.dividerAlign\"\n >\n @if (field.config.attributes.value) {\n <span [innerHTML]=\"field.config.attributes.value\"></span>\n }\n </p-divider>\n }\n\n <!-- ── Button ── -->\n @case ('button') {\n <div class=\"ngx-btn-wrap\">\n <button\n pButton\n type=\"button\"\n [id]=\"inputId(field, idSuffix)\"\n [label]=\"field.btnLabel ?? ''\"\n [icon]=\"field.config.attributes.icon ?? ''\"\n [iconPos]=\"field.config.attributes.iconPosition ?? 'left'\"\n [tabindex]=\"field.tabIndex ?? 0\"\n [disabled]=\"\n field.config.attributes.buttonRole === 'submit' ||\n field.config.attributes.type === 'submit'\n ? !formValid()\n : !!field.config.attributes.disabled\n \"\n [class.p-button-outlined]=\"\n field.config.attributes.variant === 'secondary'\n \"\n [class.p-button-text]=\"field.config.attributes.text === true\"\n [class.p-button-rounded]=\"field.config.attributes.rounded === true\"\n [class.p-button-sm]=\"field.config.attributes.size === 'sm'\"\n [class.p-button-lg]=\"field.config.attributes.size === 'lg'\"\n (click)=\"onEvent(field, $event)\"\n ></button>\n </div>\n }\n\n <!-- ── Everything else inside p-inputgroup ── -->\n @default {\n <p-inputgroup>\n @if (\n field.config.attributes.fieldPos === 'left' &&\n field.config.attributes.fieldIcon\n ) {\n <p-inputgroup-addon>\n <i [class]=\"field.config.attributes.fieldIcon\">\n {{ field.config.attributes.fieldIconText ?? '' }}\n </i>\n </p-inputgroup-addon>\n }\n\n @switch (field.config.attributes.inputType) {\n <!-- text / email / number / url -->\n @case ('text') {\n <input\n pInputText\n [id]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [type]=\"field.config.attributes.type ?? 'text'\"\n [tabindex]=\"field.tabIndex ?? 0\"\n [attr.placeholder]=\"placeholderFor(field)\"\n [attr.aria-describedby]=\"\n (errorMap()[field.formControlName!] ? field.formControlName + 'Err ' : '') +\n (field.config.attributes.info ? field.formControlName + 'Hint' : '')\n \"\n [pKeyFilter]=\"field.config.attributes.keyfilter\"\n (change)=\"onEvent(field, $event)\"\n (input)=\"onEvent(field, $event)\"\n (focus)=\"onEvent(field, $event)\"\n (blur)=\"onEvent(field, $event)\"\n (keyup)=\"onEvent(field, $event)\"\n (keydown)=\"onEvent(field, $event)\"\n (keypress)=\"onEvent(field, $event)\"\n />\n }\n\n <!-- password -->\n @case ('password') {\n <p-password\n [inputId]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [feedback]=\"field.config.attributes.feedback\"\n [toggleMask]=\"field.config.attributes.toggleMask\"\n [placeholder]=\"field.config.attributes.placeholder ?? ''\"\n appendTo=\"body\"\n (onBlur)=\"onEvent(field, $event, 'blur')\"\n (onFocus)=\"onEvent(field, $event, 'focus')\"\n >\n @if (field.config.attributes.templateHeader) {\n <ng-container\n [ngTemplateOutlet]=\"field.config.attributes.templateHeader\"\n />\n }\n @if (field.config.attributes.templateFooter) {\n <ng-container\n [ngTemplateOutlet]=\"field.config.attributes.templateFooter\"\n />\n }\n </p-password>\n }\n\n <!-- textarea -->\n @case ('textarea') {\n <textarea\n pTextarea\n [id]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [rows]=\"field.config.attributes.rows ?? 3\"\n [cols]=\"field.config.attributes.cols ?? 30\"\n [autoResize]=\"field.config.attributes.autoResize\"\n [placeholder]=\"field.config.attributes.placeholder ?? ''\"\n (change)=\"onEvent(field, $event)\"\n (input)=\"onEvent(field, $event)\"\n (focus)=\"onEvent(field, $event)\"\n (blur)=\"onEvent(field, $event)\"\n >\n </textarea>\n }\n\n <!-- select -->\n @case ('select') {\n <p-select\n [id]=\"inputId(field, idSuffix)\"\n [inputId]=\"inputId(field, idSuffix)\"\n [attr.aria-labelledby]=\"field.formControlName + 'Label'\"\n [formControlName]=\"field.formControlName!\"\n [options]=\"$any(optionsFor(field))\"\n [optionLabel]=\"field.config.attributes.optionLabel\"\n [optionValue]=\"field.config.attributes.optionValue\"\n [placeholder]=\"placeholderFor(field) ?? ''\"\n [showClear]=\"field.config.attributes.showClear\"\n [filter]=\"field.config.attributes.filter\"\n [filterBy]=\"field.config.attributes.filterBy\"\n [filterPlaceholder]=\"field.config.attributes.filterPlaceholder\"\n [loading]=\"field.config.attributes.loading\"\n [virtualScroll]=\"field.config.attributes.virtualScroll\"\n [virtualScrollItemSize]=\"\n field.config.attributes.virtualScrollItemSize\n \"\n [lazy]=\"field.config.attributes.lazy\"\n [emptyMessage]=\"field.config.attributes.emptyMessage\"\n appendTo=\"body\"\n (onChange)=\"onEvent(field, $event, 'change')\"\n (onFocus)=\"onEvent(field, $event, 'focus')\"\n (onBlur)=\"onEvent(field, $event, 'blur')\"\n (onShow)=\"onEvent(field, $event, 'show')\"\n (onHide)=\"onEvent(field, $event, 'hide')\"\n (onClear)=\"onEvent(field, $event, 'clear')\"\n (onLazyLoad)=\"onEvent(field, $event, 'lazyLoad')\"\n >\n @if (\n field.config.attributes.isTemplate &&\n field.config.attributes.template\n ) {\n <ng-container\n [ngTemplateOutlet]=\"field.config.attributes.template\"\n />\n }\n </p-select>\n }\n\n <!-- multiSelect -->\n @case ('multiSelect') {\n <p-multiselect\n [id]=\"inputId(field, idSuffix)\"\n [inputId]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [options]=\"$any(optionsFor(field))\"\n [optionLabel]=\"field.config.attributes.optionLabel\"\n [optionValue]=\"field.config.attributes.optionValue\"\n [placeholder]=\"field.config.attributes.placeholder ?? ''\"\n [filter]=\"field.config.attributes.filter\"\n [showClear]=\"field.config.attributes.showClear\"\n [selectionLimit]=\"field.config.attributes.selectionLimit\"\n [display]=\"field.config.attributes.display\"\n [loading]=\"field.config.attributes.loading\"\n [virtualScroll]=\"field.config.attributes.virtualScroll\"\n [virtualScrollItemSize]=\"\n field.config.attributes.virtualScrollItemSize\n \"\n [scrollHeight]=\"field.config.attributes.scrollHeight\"\n appendTo=\"body\"\n (onChange)=\"onEvent(field, $event, 'change')\"\n (onFocus)=\"onEvent(field, $event, 'focus')\"\n (onBlur)=\"onEvent(field, $event, 'blur')\"\n (onClear)=\"onEvent(field, $event, 'clear')\"\n (onHide)=\"onEvent(field, $event, 'hide')\"\n (onRemove)=\"onEvent(field, $event, 'remove')\"\n (onSelectAll)=\"onEvent(field, $event, 'select')\"\n >\n </p-multiselect>\n }\n\n <!-- autocomplete -->\n @case ('autocomplete') {\n <p-autocomplete\n [id]=\"inputId(field, idSuffix)\"\n [inputId]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [placeholder]=\"field.config.attributes.placeholder ?? ''\"\n [suggestions]=\"field.config.attributes.suggestions\"\n [optionLabel]=\"field.config.attributes.optionLabel\"\n [multiple]=\"field.config.attributes.multiple\"\n [forceSelection]=\"field.config.attributes.forceSelection\"\n [dropdown]=\"field.config.attributes.dropdown\"\n [showClear]=\"field.config.attributes.showClear\"\n [completeOnFocus]=\"field.config.attributes.completeOnFocus\"\n [minLength]=\"field.config.attributes.minLength ?? 1\"\n [delay]=\"field.config.attributes.delay ?? 300\"\n [virtualScroll]=\"field.config.attributes.virtualScroll\"\n [virtualScrollItemSize]=\"\n field.config.attributes.virtualScrollItemSize\n \"\n [scrollHeight]=\"field.config.attributes.scrollHeight\"\n appendTo=\"body\"\n (completeMethod)=\"onEvent(field, $event, 'complete')\"\n (onSelect)=\"onEvent(field, $event, 'select')\"\n (onUnselect)=\"onEvent(field, $event, 'unselect')\"\n (onAdd)=\"onEvent(field, $event, 'add')\"\n (onFocus)=\"onEvent(field, $event, 'focus')\"\n (onBlur)=\"onEvent(field, $event, 'blur')\"\n (onClear)=\"onEvent(field, $event, 'clear')\"\n (onInputKeydown)=\"onEvent(field, $event, 'inputKeydown')\"\n >\n </p-autocomplete>\n }\n\n <!-- toggle -->\n @case ('toggle') {\n <p-toggleswitch\n [formControlName]=\"field.formControlName!\"\n [inputId]=\"inputId(field, idSuffix)\"\n [attr.aria-labelledby]=\"field.formControlName + 'Label'\"\n (onChange)=\"onEvent(field, $event, 'change')\"\n />\n }\n\n <!-- checkbox -->\n @case ('checkbox') {\n <p-checkbox\n [inputId]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [name]=\"field.config.attributes.name ?? field.formControlName!\"\n [value]=\"field.config.attributes.value\"\n (onChange)=\"onEvent(field, $event, 'change')\"\n />\n }\n\n <!-- radio -->\n @case ('radio') {\n @for (opt of $any(optionsFor(field)); track $index) {\n <div class=\"ngx-radio-item\">\n <p-radiobutton\n [inputId]=\"field.formControlName + '_' + $index\"\n [formControlName]=\"field.formControlName!\"\n [name]=\"field.formControlName!\"\n [value]=\"\n opt[field.config.attributes.optionValue ?? 'value']\n \"\n (onClick)=\"onEvent(field, $event, 'change')\"\n />\n <label [for]=\"field.formControlName + '_' + $index\">\n {{ opt[field.config.attributes.optionLabel ?? 'label'] }}\n </label>\n </div>\n }\n }\n\n <!-- datePicker / time / month / year -->\n @case ('datePicker') {\n <p-datepicker\n [inputId]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [placeholder]=\"field.config.attributes.placeholder ?? ''\"\n [showIcon]=\"field.config.attributes.showIcon\"\n [minDate]=\"minDateFor(field)!\"\n [maxDate]=\"maxDateFor(field)!\"\n [selectionMode]=\"$any(field.config.attributes.selectionMode)\"\n [readonlyInput]=\"field.config.attributes.readonlyInput\"\n [showButtonBar]=\"field.config.attributes.showButtonBar\"\n [showTime]=\"field.config.attributes.showTime\"\n [hourFormat]=\"field.config.attributes.hourFormat\"\n [timeOnly]=\"field.config.attributes.timeOnly\"\n [view]=\"$any(field.config.attributes.view)\"\n [dateFormat]=\"field.config.attributes.dateFormat\"\n [numberOfMonths]=\"field.config.attributes.numberOfMonths ?? 1\"\n [showClear]=\"field.config.attributes.showClear\"\n appendTo=\"body\"\n (onSelect)=\"onEvent(field, $event, 'select')\"\n (onBlur)=\"onEvent(field, $event, 'blur')\"\n (onFocus)=\"onEvent(field, $event, 'focus')\"\n (onClear)=\"onEvent(field, $event, 'clear')\"\n >\n </p-datepicker>\n }\n\n @case ('time') {\n <p-datepicker\n [inputId]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [placeholder]=\"field.config.attributes.placeholder ?? ''\"\n [showIcon]=\"true\"\n [iconDisplay]=\"'input'\"\n [timeOnly]=\"true\"\n [showTime]=\"true\"\n [hourFormat]=\"field.config.attributes.hourFormat ?? '24'\"\n appendTo=\"body\"\n (onSelect)=\"onEvent(field, $event, 'select')\"\n />\n }\n\n @case ('month') {\n <p-datepicker\n [inputId]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [placeholder]=\"field.config.attributes.placeholder ?? ''\"\n [showIcon]=\"true\"\n [view]=\"'month'\"\n [dateFormat]=\"field.config.attributes.dateFormat ?? 'mm/yy'\"\n [readonlyInput]=\"true\"\n appendTo=\"body\"\n (onSelect)=\"onEvent(field, $event, 'select')\"\n />\n }\n\n @case ('year') {\n <p-datepicker\n [inputId]=\"inputId(field, idSuffix)\"\n [formControlName]=\"field.formControlName!\"\n [placeholder]=\"field.config.attributes.placeholder ?? ''\"\n [showIcon]=\"true\"\n [view]=\"'year'\"\n [dateFormat]=\"field.config.attributes.dateFormat ?? 'yy'\"\n [readonlyInput]=\"true\"\n appendTo=\"body\"\n (onSelect)=\"onEvent(field, $event, 'select')\"\n />\n }\n\n <!-- slider -->\n @case ('slider') {\n <p-slider\n [formControlName]=\"field.formControlName!\"\n [min]=\"field.config.attributes.min ?? 0\"\n [max]=\"field.config.attributes.max ?? 100\"\n [step]=\"field.config.attributes.step ?? 1\"\n [range]=\"field.config.attributes.range\"\n [orientation]=\"\n field.config.attributes.orientation ?? 'horizontal'\n \"\n (onChange)=\"onEvent(field, $event, 'change')\"\n />\n }\n\n <!-- rating -->\n @case ('rating') {\n <p-rating\n [formControlName]=\"field.formControlName!\"\n [stars]=\"field.config.attributes.stars ?? 5\"\n (onRate)=\"onEvent(field, $event, 'change')\"\n />\n }\n\n <!-- colorPicker -->\n @case ('colorPicker') {\n <p-colorpicker\n [formControlName]=\"field.formControlName!\"\n [inline]=\"field.config.attributes.inline\"\n (onChange)=\"onEvent(field, $event, 'change')\"\n />\n }\n }\n\n @if (\n field.config.attributes.fieldPos === 'right' &&\n field.config.attributes.fieldIcon\n ) {\n <p-inputgroup-addon>\n <i [class]=\"field.config.attributes.fieldIcon\">\n {{ field.config.attributes.fieldIconText ?? '' }}\n </i>\n </p-inputgroup-addon>\n }\n </p-inputgroup>\n }\n }\n </ng-container>\n</ng-template>\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n inject,\n input,\n output,\n} from '@angular/core';\nimport { NgClass } from '@angular/common';\nimport { ButtonModule } from 'primeng/button';\n\nimport {\n FormEngineEvent,\n FormEngineService,\n FormSchema,\n} from '@ngx-json-forms/core';\n\nimport { NgxJsonFormComponent } from './ngx-form-engine-primeng.component';\n\n/**\n * Wizard-style wrapper that drives `<ngx-json-form>` step-by-step using the\n * `FormSchema.steps` definition. Renders a header strip with step indicators,\n * the current step's fields, and Back / Next / Submit controls.\n */\n@Component({\n selector: 'ngx-json-form-stepper',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgxJsonFormComponent, ButtonModule, NgClass],\n styleUrl: './ngx-json-form-stepper.component.scss',\n template: `\n @if (schema().steps?.length) {\n <div class=\"ngx-stepper\">\n <!-- Step indicators -->\n <ol class=\"ngx-stepper-bar\">\n @for (step of schema().steps; track step.id) {\n <li\n class=\"ngx-stepper-item\"\n [ngClass]=\"{\n active: $index === activeIndex(),\n done: $index < activeIndex()\n }\"\n (click)=\"jumpTo($index)\"\n >\n <span class=\"ngx-stepper-num\">\n @if ($index < activeIndex()) {\n <i class=\"pi pi-check\"></i>\n } @else {\n {{ $index + 1 }}\n }\n </span>\n <span class=\"ngx-stepper-label\">\n @if (step.icon) {\n <i [class]=\"step.icon\"></i>\n }\n {{ step.title }}\n </span>\n </li>\n }\n </ol>\n\n <!-- Step body -->\n @if (activeStep(); as step) {\n @if (step.description) {\n <p class=\"ngx-stepper-desc\">{{ step.description }}</p>\n }\n <ngx-json-form\n [schema]=\"schema()\"\n [stepFields]=\"step.fields\"\n (formChange)=\"formChange.emit($event)\"\n (formSubmit)=\"onSubmit($event)\"\n />\n }\n\n <!-- Controls -->\n <div class=\"ngx-stepper-actions\">\n <button\n pButton\n type=\"button\"\n class=\"p-button-text\"\n label=\"Back\"\n icon=\"pi pi-arrow-left\"\n [disabled]=\"activeIndex() === 0\"\n (click)=\"back()\"\n ></button>\n @if (!isLast()) {\n <button\n pButton\n type=\"button\"\n label=\"Next\"\n icon=\"pi pi-arrow-right\"\n iconPos=\"right\"\n (click)=\"next()\"\n ></button>\n } @else {\n <button\n pButton\n type=\"button\"\n [label]=\"submitLabel()\"\n icon=\"pi pi-check\"\n iconPos=\"right\"\n [disabled]=\"!formService.formValid()\"\n (click)=\"submit()\"\n ></button>\n }\n </div>\n </div>\n }\n `,\n})\nexport class NgxJsonFormStepperComponent {\n readonly schema = input.required<FormSchema>();\n readonly submitLabel = input<string>('Submit');\n\n readonly formSubmit = output<FormEngineEvent>();\n readonly formChange = output<FormEngineEvent>();\n\n protected readonly formService = inject(FormEngineService);\n\n readonly activeIndex = computed(() => this.formService.activeStepIndex());\n readonly activeStep = computed(() => this.formService.activeStep());\n\n readonly isLast = computed(() => {\n const steps = this.schema().steps ?? [];\n return this.activeIndex() === steps.length - 1;\n });\n\n constructor() {\n // Reset the wizard whenever the schema input changes\n effect(() => {\n this.schema();\n this.formService.goToStep(0);\n });\n }\n\n protected back(): void {\n this.formService.prevStep();\n }\n\n protected next(): void {\n this.formService.nextStep();\n }\n\n protected jumpTo(i: number): void {\n if (i <= this.activeIndex()) this.formService.goToStep(i);\n }\n\n protected submit(): void {\n if (!this.formService.markAllAsTouchedAndValidate()) return;\n const values = this.formService.buildSubmitPayload();\n this.formSubmit.emit({\n field: { config: { attributes: { inputType: 'button', buttonRole: 'submit' } } } as never,\n values,\n valid: true,\n type: 'submit',\n });\n }\n\n /** Pass-through when the inner form emits formSubmit (e.g. via an inline button) */\n protected onSubmit(e: FormEngineEvent): void {\n this.formSubmit.emit(e);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ngx-json-forms/primeng",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "PrimeNG adapter for ngx-json-forms — renders JSON-defined forms using PrimeNG components.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"angular",
|
|
7
|
+
"primeng",
|
|
8
|
+
"form",
|
|
9
|
+
"json-form",
|
|
10
|
+
"form-engine",
|
|
11
|
+
"dynamic-forms",
|
|
12
|
+
"ngx-json-forms"
|
|
13
|
+
],
|
|
14
|
+
"author": "Raghvendrasing Pal <dev.raghvendrasing@gmail.com>",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/Raghav-Pal-dev/ngx-json-forms"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/Raghav-Pal-dev/ngx-json-forms#readme",
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@angular/common": ">=19.0.0",
|
|
23
|
+
"@angular/core": ">=19.0.0",
|
|
24
|
+
"@angular/forms": ">=19.0.0",
|
|
25
|
+
"@ngx-json-forms/core": "^1.0.0",
|
|
26
|
+
"primeng": ">=19.0.0",
|
|
27
|
+
"rxjs": "~7.8.0"
|
|
28
|
+
},
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"module": "fesm2022/ngx-json-forms-primeng.mjs",
|
|
31
|
+
"typings": "types/ngx-json-forms-primeng.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
"./package.json": {
|
|
34
|
+
"default": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./types/ngx-json-forms-primeng.d.ts",
|
|
38
|
+
"default": "./fesm2022/ngx-json-forms-primeng.mjs"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"type": "module",
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"tslib": "^2.3.0"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { computed, Type } from '@angular/core';
|
|
3
|
+
import { FormGroup, FormArray, FormControl } from '@angular/forms';
|
|
4
|
+
import * as _ngx_json_forms_core from '@ngx-json-forms/core';
|
|
5
|
+
import { FormField, FormSchema, FormEngineEvent, FormEngineService, ImageUploadService, FieldRegistry, FormEngineEventType } from '@ngx-json-forms/core';
|
|
6
|
+
|
|
7
|
+
declare class NgxJsonFormComponent {
|
|
8
|
+
readonly formTitle: _angular_core.InputSignal<string>;
|
|
9
|
+
readonly fieldsInput: _angular_core.InputSignal<FormField[]>;
|
|
10
|
+
/** Optional schema input — supersedes `fieldsInput` when provided. */
|
|
11
|
+
readonly schema: _angular_core.InputSignal<FormSchema | null>;
|
|
12
|
+
/** Only render fields in the given step indices (used by the stepper wrapper). */
|
|
13
|
+
readonly stepFields: _angular_core.InputSignal<FormField[] | null>;
|
|
14
|
+
readonly formSubmit: _angular_core.OutputEmitterRef<FormEngineEvent>;
|
|
15
|
+
readonly formChange: _angular_core.OutputEmitterRef<FormEngineEvent>;
|
|
16
|
+
protected readonly formService: FormEngineService;
|
|
17
|
+
protected readonly uploadService: ImageUploadService;
|
|
18
|
+
protected readonly fieldRegistry: FieldRegistry;
|
|
19
|
+
readonly fields: _angular_core.WritableSignal<FormField[]>;
|
|
20
|
+
readonly formGroup: _angular_core.WritableSignal<FormGroup<any>>;
|
|
21
|
+
readonly ready: _angular_core.WritableSignal<boolean>;
|
|
22
|
+
/** Async-loaded options keyed by formControlName */
|
|
23
|
+
readonly asyncOptions: _angular_core.WritableSignal<Record<string, unknown[]>>;
|
|
24
|
+
private readonly formStatusTick;
|
|
25
|
+
private readonly focusedMap;
|
|
26
|
+
/** Subscriptions for async option re-loads; disposed on every rebuild. */
|
|
27
|
+
private optionLoaderSubs;
|
|
28
|
+
readonly visibleFields: _angular_core.Signal<FormField[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Track patchTick so .valid (a plain object property) re-reads after every
|
|
31
|
+
* form change. Without this, the submit-button disabled binding stays stuck
|
|
32
|
+
* on the FormGroup's initial (invalid) state.
|
|
33
|
+
*/
|
|
34
|
+
readonly formValid: _angular_core.Signal<boolean>;
|
|
35
|
+
protected placeholderVisibilityMap: Record<string, ReturnType<typeof computed>>;
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the placeholder string to render for a field. Safe for nested
|
|
38
|
+
* fields (repeater itemFields, group groupFields) whose formControlName
|
|
39
|
+
* isn't pre-registered in `placeholderVisibilityMap` — those fall back to
|
|
40
|
+
* the raw `field.placeholder` since they don't participate in floatLabel.
|
|
41
|
+
*/
|
|
42
|
+
protected placeholderFor(field: FormField): string | null;
|
|
43
|
+
readonly errorMap: _angular_core.Signal<Record<string, string | null>>;
|
|
44
|
+
constructor();
|
|
45
|
+
private buildForm;
|
|
46
|
+
private disposeOptionLoaderSubs;
|
|
47
|
+
private loadAsyncOptions;
|
|
48
|
+
protected customRenderer(field: FormField): Type<unknown> | undefined;
|
|
49
|
+
protected customRendererInputs(field: FormField): Record<string, unknown>;
|
|
50
|
+
protected minDateFor(field: FormField): Date | undefined;
|
|
51
|
+
protected maxDateFor(field: FormField): Date | undefined;
|
|
52
|
+
protected optionsFor(field: FormField): unknown[];
|
|
53
|
+
protected getArray(name: string): FormArray | null;
|
|
54
|
+
protected addRepeaterRow(field: FormField): void;
|
|
55
|
+
protected removeRepeaterRow(field: FormField, i: number): void;
|
|
56
|
+
protected rowGroup(field: FormField, i: number): FormGroup;
|
|
57
|
+
/**
|
|
58
|
+
* DOM id for a field's input element. Scoped by row index when the field
|
|
59
|
+
* lives inside a repeater so the same `formControlName` across rows
|
|
60
|
+
* doesn't produce duplicate ids (HTML spec violation + breaks
|
|
61
|
+
* <label for>, aria-describedby, and document.querySelector lookups).
|
|
62
|
+
*/
|
|
63
|
+
protected inputId(field: FormField, suffix?: number | string): string;
|
|
64
|
+
/**
|
|
65
|
+
* Resolve the validation message for a single field inside a repeater row.
|
|
66
|
+
* Mirrors errorMap() but for FormGroup rows that aren't tracked in the
|
|
67
|
+
* top-level fields signal.
|
|
68
|
+
*/
|
|
69
|
+
protected resolveRowError(row: FormGroup, sub: FormField): string | null;
|
|
70
|
+
/** Central event handler. Accepts `unknown` because PrimeNG emits custom event objects. */
|
|
71
|
+
onEvent(field: FormField, event: unknown, eventType?: FormEngineEventType): Promise<void>;
|
|
72
|
+
removeImage(field: FormField, image: string): void;
|
|
73
|
+
private buildPayload;
|
|
74
|
+
private emitChange;
|
|
75
|
+
private triggerTick;
|
|
76
|
+
protected getControl(name: string): FormControl;
|
|
77
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgxJsonFormComponent, never>;
|
|
78
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgxJsonFormComponent, "ngx-json-form", never, { "formTitle": { "alias": "formTitle"; "required": false; "isSignal": true; }; "fieldsInput": { "alias": "fieldsInput"; "required": false; "isSignal": true; }; "schema": { "alias": "schema"; "required": false; "isSignal": true; }; "stepFields": { "alias": "stepFields"; "required": false; "isSignal": true; }; }, { "formSubmit": "formSubmit"; "formChange": "formChange"; }, never, never, true, never>;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Wizard-style wrapper that drives `<ngx-json-form>` step-by-step using the
|
|
83
|
+
* `FormSchema.steps` definition. Renders a header strip with step indicators,
|
|
84
|
+
* the current step's fields, and Back / Next / Submit controls.
|
|
85
|
+
*/
|
|
86
|
+
declare class NgxJsonFormStepperComponent {
|
|
87
|
+
readonly schema: _angular_core.InputSignal<FormSchema>;
|
|
88
|
+
readonly submitLabel: _angular_core.InputSignal<string>;
|
|
89
|
+
readonly formSubmit: _angular_core.OutputEmitterRef<FormEngineEvent>;
|
|
90
|
+
readonly formChange: _angular_core.OutputEmitterRef<FormEngineEvent>;
|
|
91
|
+
protected readonly formService: FormEngineService;
|
|
92
|
+
readonly activeIndex: _angular_core.Signal<number>;
|
|
93
|
+
readonly activeStep: _angular_core.Signal<_ngx_json_forms_core.FormStep | null>;
|
|
94
|
+
readonly isLast: _angular_core.Signal<boolean>;
|
|
95
|
+
constructor();
|
|
96
|
+
protected back(): void;
|
|
97
|
+
protected next(): void;
|
|
98
|
+
protected jumpTo(i: number): void;
|
|
99
|
+
protected submit(): void;
|
|
100
|
+
/** Pass-through when the inner form emits formSubmit (e.g. via an inline button) */
|
|
101
|
+
protected onSubmit(e: FormEngineEvent): void;
|
|
102
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgxJsonFormStepperComponent, never>;
|
|
103
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgxJsonFormStepperComponent, "ngx-json-form-stepper", never, { "schema": { "alias": "schema"; "required": true; "isSignal": true; }; "submitLabel": { "alias": "submitLabel"; "required": false; "isSignal": true; }; }, { "formSubmit": "formSubmit"; "formChange": "formChange"; }, never, never, true, never>;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export { NgxJsonFormComponent, NgxJsonFormStepperComponent };
|