SKILL.md
$27
- Directives as Glue: The
[formField]directive binds a DOM element (native input or custom control) to aFieldNode.
It handles:
- Syncing the value between the DOM and the Signal.
- Reflecting state (valid, touched, etc.) to the UI.
- Handling user interaction events (blur, input).
Key Components
1. FieldNode ( src/field/node.ts )
The central internal class representing a single field in the form graph. It aggregates several state managers:
structure: Manages parent/child relationships and signal slicing.
validationState: Computesvalid,invalid,errorssignals.
nodeState: Trackstouched,dirty,pristine.
metadataState: Stores metadata likemin,max,required.
submitState: Tracks submission status and server errors.
2. ValidationState ( src/field/validation.ts )
Manages the complexity of validation:
- Synchronous Errors: Derived from schema rules.
- Asynchronous Errors: Handled via signals, including 'pending' states.
- Tree Errors: Errors that bubble up or are targeted at specific fields.
- Submission Errors: Server-side errors injected imperatively via
submit().
3. FormField Directive ( src/directive/form_field_directive.ts )
The bridge between the FieldNode and the DOM.
- Selector:
[formField]
- It supports:
- Native Elements:
<input>,<select>,<textarea>.
- Custom Controls: Components implementing
FormUiControlorFormValueControl.
- Legacy Interop: Components implementing
ControlValueAccessor(viaInteropNgControl).
4. Schema ( src/api/structure.ts & src/api/rules )
Defines the behavior.
- Created via
schema(fn).
- Applied via
apply(path, schema).
- Rules include validators (
required,pattern,min,max) and state modifiers (disabled,hidden).
Data Flow
- Read:
form.field.value()reads directly from the underlying signal (projected to the specific path).
- Write: Writing to the form (e.g., via UI) updates the underlying signal.
- Validation: A computed effect observes the value signal and runs validators defined in the schema.
Usage Example (Conceptual)
// 1. Define Model
const user = signal({name: '', age: 0});
// 2. Define Schema
const userRules = schema((u) => {
required(u.name);
min(u.age, 18);
});
// 3. Create Form
const userForm = form(user, userRules); // OR apply(userForm, userRules)
// 4. Bind in Template
// <input [formField]="userForm.name">
Important Files
packages/forms/signals/src/api/structure.ts: Public API entry points (form,apply).
packages/forms/signals/src/api/control.ts: Interfaces for custom controls (FormUiControl).
packages/forms/signals/src/field/node.ts: TheFieldNodeimplementation.
packages/forms/signals/src/directive/form_field_directive.ts: The[formField]directive.
Supplemental Information
- Compiler &#x26; Core Integration: Details how
[formField]hooks into type-checking and the runtime.