reference-signal-forms — Claude Code skill: install
Explains Angular signal-based forms and helps agents navigate packages/forms/signals before changing its architecture or field bindings.
npx skills add angular/angular --skill reference-signal-forms -a claude-codeWhat reference-signal-forms does
This skill explains Angular's signal-based forms model. A WritableSignal<T> stores the value as the source of truth, while the form projects field state such as validity, dirty, and touched. Calling form(signal) returns a proxy FieldTree; nested properties resolve their corresponding FieldNode lazily.
It connects Schema rules with validation and state modifiers such as disabled and hidden. It also covers how [formField] binds native elements or custom controls to a field node, plus the internal structure of validation, metadata, submission, and server errors. If you are changing packages/forms/signals, load this skill first because that directory is its specific scope.
What it helps with
- map the architecture of Angular signal-based forms
- trace a field value back to its signal
- understand how
FieldTreeresolvesFieldNodeobjects - define validation rules with
Schemaandapply - check how
[formField]binds a DOM control
Example prompts for the agent
- Explain the architecture under `packages/forms/signals` before I edit it.
- Show how `WritableSignal<T>`, `FieldTree`, and `Schema` fit together in this code.
- Check how `[formField]` syncs a DOM value with the underlying signal.
How to install reference-signal-forms
1Skills CLI (Vercel)
npx skills add angular/angular --skill reference-signal-forms -a claude-code2Manually: put the files in place
~/.claude/skills/reference-signal-forms/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/reference-signal-forms/
1Skills CLI (Vercel)
npx skills add angular/angular --skill reference-signal-forms -a codex2Manually: put the files in place
.agents/skills/reference-signal-forms/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add angular/angular --skill reference-signal-forms -a cursor2Manually: put the files in place
.cursor/skills/reference-signal-forms/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install angular/angular reference-signal-forms2Manually: put the files in place
.github/skills/reference-signal-forms/SKILL.md1Skills CLI (Vercel)
npx skills add angular/angular --skill reference-signal-forms -a gemini-cli2Platform CLI
gemini skills install https://github.com/angular/angular --path .agent/skills/reference-signal-formsManually: put the files in place
.devin/skills/reference-signal-forms/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add angular/angular --skill reference-signal-forms -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set5
The whole set →Similar
Questions about reference-signal-forms
How do I install `reference-signal-forms` in Claude Code?
Run the steps in order: npx skills add angular/angular --skill reference-signal-forms -a claude-code, then run npx skills add angular/angular --skill reference-signal-forms -a claude-code again. The skill file is at ~/.claude/skills/reference-signal-forms/SKILL.md.
What does `reference-signal-forms` do?
It explains Angular signal-based forms through the WritableSignal<T> model, proxy-based FieldTree traversal, schemas, field nodes, and [formField]. It also covers synchronous, asynchronous, and submission errors.
When should I use `reference-signal-forms`?
Use it before working on code in packages/forms/signals. That area follows a model different from Reactive Forms and Template-driven forms.
Source text
SKILL.md · MIT
---
name: reference-signal-forms
description: Explains the mental model and architecture of the code under `packages/forms/signals`. You MUST use this skill any time you plan to work with code in `packages/forms/signals`
---
# Signal Forms Architecture
The `packages/forms/signals` directory contains the signal-based forms API for Angular.
This system differs significantly from the existing Reactive and Template-driven forms.
## Mental Model
1. **Model-Driven**: The system is built around a `WritableSignal<T>` which serves as the **single source of truth**.
Unlike Reactive Forms where the `FormControl` holds the value, here the `Signal` holds the value.
The form is merely a _view_ or _projection_ of that signal, adding form-specific state (validity, dirty, touched).
2. **Proxy-Based Traversal**: The form API (`form(signal)`) returns a `FieldTree`. This object is a **Proxy**.
It allows accessing nested fields (e.g., `myForm.user.name`) without manually creating control groups.
Accessing a property on the proxy lazily resolves or creates the corresponding `FieldNode`.
3. **Schema-Based Logic**: Validation, disabled state, and other metadata are defined separately via **Schemas**.
Schemas are applied to the form structure using functions like `apply`, `applyEach` (for arrays), and `applyWhen`.
This separates the _structure_ of the data from the _rules_ governing it.
4. **Directives as Glue**: The `[formField]` directive binds a DOM element (native input or custom control) to a `FieldNode`.
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`: Computes `valid`, `invalid`, `errors` signals.
- `nodeState`: Tracks `touched`, `dirty`, and derived logical state.
- `metadataState`: Stores metadata like `min`, `max`, `required`.
- `submitState`: Tracks submission status and server errors.
### 2. `FieldValidationState` (`src/field/validation.ts`)
Implements `ValidationState` and 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.ts`)
The bridge between the `FieldNode` and the DOM.
- Selector: `[formField]`
- It supports:
- **Native Elements**: `<input>`, `<select>`, `<textarea>`.
- **Custom Controls**: Components implementing `FormValueControl` or `FormCheckboxControl`.
- **Legacy Interop**: Components implementing `ControlValueAccessor` (via `InteropNgControl`).
### 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
1. **Read**: `form.field().value()` reads directly from the underlying signal (projected to the specific path).
2. **Write**: Writing to the form (e.g., via UI) updates the underlying signal.
3. **Validation**: A computed effect observes the value signal and runs validators defined in the schema.
## Usage Example (Conceptual)
```typescript
// 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`: The `FieldNode` implementation.
- `packages/forms/signals/src/directive/form_field.ts`: The `[formField]` directive.
## Supplemental Information
- [Compiler & Core Integration](references/integration.md): Details how `[formField]` hooks into type-checking and the runtime.
© angular · MIT · angular/angular