@flusys/ng-form-builder
v9.2.1
Published
Dynamic form builder for FLUSYS Angular applications
Readme
@flusys/ng-form-builder
Dynamic form builder for FLUSYS — drag-and-drop schema editor (fb-form-builder), runtime form renderer (fb-form-viewer), and result viewer (fb-form-result-viewer).
Installation
npm install @flusys/ng-form-builder @angular/cdk1. Add Routes
// app.routes.ts
import { FORM_BUILDER_ROUTES } from '@flusys/ng-form-builder';
export const routes: Routes = [
{
path: 'forms',
loadChildren: () => FORM_BUILDER_ROUTES,
},
];2. Embed the Builder Component
fb-form-builder provides a three-panel layout: field palette (left), drag-and-drop canvas (center), properties editor (right). FormBuilderStateService is provided at component level automatically — do not add it to root providers.
import { FormBuilderComponent } from '@flusys/ng-form-builder';
@Component({
imports: [FormBuilderComponent],
template: `
<fb-form-builder
[schema]="schema()"
(schemaChange)="schema.set($event)" // emits on every canvas edit
(schemaSave)="onSave($event)" // emits when toolbar Save is clicked
(schemaExport)="onExport($event)" // emits when toolbar Export is clicked
/>
`,
})
export class FormEditorPageComponent {
readonly schema = signal<IFormSchema | null>(null);
onSave(schema: IFormSchema): void {
// persist schema to backend
}
}Pass null (or omit [schema]) to start with an empty form.
3. Render a Form for Submission
fb-form-viewer renders an IFormSchema for end-user submission. It handles section navigation, progress bar, client-side validation, and conditional field show/hide.
import { FormViewerComponent } from '@flusys/ng-form-builder';
@Component({
imports: [FormViewerComponent],
template: `
<fb-form-viewer
[schema]="formSchema"
[initialValues]="draftValues" // optional — pre-populate fields
[disabled]="isReadOnly" // optional — prevents input
[showHeader]="true" // optional — shows form name/description
[isSubmitting]="submitting()" // optional — shows loading on submit button
(submitted)="onSubmit($event)" // emits Record<string, unknown>
(valueChanged)="onChange($event)"
(saveDraft)="onDraft($event)"
(cancelled)="onCancel()"
/>
`,
})
export class FormViewPageComponent {
formSchema!: IFormSchema;
submitting = signal(false);
onSubmit(values: Record<string, unknown>): void {
this.submitting.set(true);
// POST values to backend
}
}4. View Collected Results
import { FormResultViewerComponent } from '@flusys/ng-form-builder';
@Component({
imports: [FormResultViewerComponent],
template: `
<fb-form-result-viewer [schema]="schema" [result]="submission" />
`,
})
export class ResultPageComponent { }For an email_verified form, IFormResult/IFormSubmission carries a submitterEmail
(the verified anonymous identity, or null for a logged-in/PUBLIC submission).
fb-form-result-viewer shows it in the metadata row when present, and both the JSON and
PDF exports from FormResultViewerPageComponent include it alongside submittedById.
5. Public Access Types (incl. Email Verification)
lib-public-form-page (routed at forms/public/:id, see FORM_BUILDER_ROUTES) renders a form for anonymous or logged-in visitors based on the form's accessType: public (no identity), authenticated/action_group (requires app login), and email_verified — anonymous visitors verify a one-time email code, while an already-logged-in visitor is auto-identified by their account email and skips it entirely. This is handled automatically by the page; no extra wiring is needed beyond the routes above. On the form details page, the action_group required permissions are an AND / OR rule (permissionLogic, an ILogicNode) edited with ng-shared's <lib-permission-logic scope="company">, whose rows list the company's permitted IAM actions through ACTION_PROVIDER; an empty rule is saved as null (any signed-in user), and saving is blocked while a row or group is empty (registered by provideIamProviders()), so ng-form-builder makes no IAM calls of its own.
The email-verified flow is only offered in the form builder's Access Type dropdown when the email service is enabled in APP_CONFIG (isServiceEnabled(appConfig, 'email')) — it needs a backend FORM_BUILDER_EMAIL_PROVIDER configured to actually send codes (see the nestjs-form-builder README). The verified email becomes a real server-side identity, so the form's responseMode setting (Single/Multiple Responses, set in the builder) is enforced by the backend for these forms exactly as it already is for authenticated submissions — a returning visitor with responseMode: 'multiple' is not asked to re-verify (a 30-day sliding session, stored as form-email-token-<formId> in localStorage).
6. Computed Fields
The builder's Computed Fields tab (ComputedFieldsEditorComponent) edits settings.computedFields. Each rule is an optional condition (fb-condition-group-editor, nested AND / OR groups) and a value (fb-expression-editor). Both are recursive: any operand, part, function argument or if / else branch is another expression, so new cases are combinations, not new computation types.
Expression types: fixed value, field, math, combine (with optional separator), text template ({{ field_name }}, click a field to insert it), function (text, regex, number, date, first-non-empty) and if / else. The JSON matches @flusys/nestjs-shared expressions; the backend evaluates it on submit and validates it on save. A computed field can reference computed fields above it (computed.<key>).
Breaking (v9): rules saved in the old computation shape are not converted; rebuild those computed fields in the builder before saving the form again.
License
MIT © FLUSYS
