Define fields.
Attach triggers.
Ship the form.
A TypeScript-first form engine for Angular. Async validation, API-driven selects, dynamic arrays, lazy-loaded components, and custom field models all declared in field models, no component glue.
1new UserName({
2 required: true,
3 triggers: [
4 {
5 on: FormFieldEventType.CHANGE, reacts to input
6 action: TriggerAction.VALIDATE_ASYNC, async validation
7 fetchUrl: "/api/check/$value",
8 },
9 ],
10})
11
12new SelectField({
13 key: "region",
14 triggers: [{
15 on: FormFieldEventType.INIT, fires on load
16 action: TriggerAction.FETCH,
17 fetchUrl: "/api/regions",
18 projection: {
19 target: "options", patches the field
20 source: "results",
21 },
22 }],
23})
All the hard parts, declared.
The common patterns in complex forms, extracted into a composable model layer.
One object replaces a subscriber.
Triggers are the unit of reactivity in Preforms. Attach them to any field, point them at an event, and let the engine handle the rest.
Async validation hits your API without handwritten glue.
A dependent select fetches its options when a parent value changes.
A dialog opens when an icon is clicked and closes on a button command.
No RxJS, no ViewChild, no parent component managing it all.
1new UserName({
2 triggers: [{
3 on: FormFieldEventType.CHANGE,
4 action: TriggerAction.VALIDATE_ASYNC,
5 fetchUrl: "/api/username/$value",
6 }],
7})
1new SelectField({
2 key: "city",
3 triggers: [{
4 on: FormFieldEventType.CHANGE,
5 watchField: "country",
6 action: TriggerAction.FETCH,
7 fetchUrl: "/api/cities/$country",
8 projection: { target: "options" },
9 }],
10})
See what's possible.
Every example is interactive and linked to source.
1// 1. Extend FormField
2export class EditorField extends FormField<string> {
3 constructor(key: string) {
4 super({ component: "editor", key });
5 }
6}
7
8// 2. Register with lazy loader
9provideDynamicFormLazyFields([{
10 type: "editor",
11 loader: () =>
12 import("./editor.component")
13 .then(m => m.EditorComponent),
14}])
Custom fields in two steps.
The engine doesn't know what an "editor" is. You tell it. Extend FormField, register an Angular component against the type key, and the renderer handles the rest.
Rich text editors, date pickers, map inputs, anything Angular can render.
Components load lazily, so there is no bundle cost until the field appears.
Custom fields participate in triggers, validation, and aggregates like any built-in.
Ready to stop writing form glue?
Preforms is open source and MIT licensed. The docs have working examples for every feature.