reference-signal-forms
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSignal Forms Architecture
Signal表单架构
The directory contains an experimental, signal-based forms API for Angular.
This system differs significantly from the existing Reactive and Template-driven forms.
packages/forms/signalspackages/forms/signalsMental Model
思维模型
-
Model-Driven: The system is built around awhich serves as the single source of truth. Unlike Reactive Forms where the
WritableSignal<T>holds the value, here theFormControlholds the value. The form is merely a view or projection of that signal, adding form-specific state (validity, dirty, touched).Signal -
Proxy-Based Traversal: The form API () returns a
form(signal). This object is a Proxy. It allows accessing nested fields (e.g.,FieldTree) without manually creating control groups. Accessing a property on the proxy lazily resolves or creates the correspondingmyForm.user.name.FieldNode -
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(for arrays), andapplyEach. This separates the structure of the data from the rules governing it.applyWhen -
Directives as Glue: Thedirective binds a DOM element (native input or custom control) to a
[formField]. It handles:FieldNode- Syncing the value between the DOM and the Signal.
- Reflecting state (valid, touched, etc.) to the UI.
- Handling user interaction events (blur, input).
-
模型驱动:该系统围绕构建,它作为单一数据源。 与响应式表单中由
WritableSignal<T>存储值不同,此处由FormControl存储值。表单仅仅是该Signal的一个_视图_或_投影_,添加了表单特有的状态(有效性、脏值、已触碰)。Signal -
基于代理的遍历:表单API()返回一个
form(signal)对象,这是一个Proxy(代理)。 它允许访问嵌套字段(例如FieldTree),而无需手动创建控件组。 访问代理上的属性会惰性解析或创建对应的myForm.user.name。FieldNode -
基于Schema的逻辑:验证规则、禁用状态和其他元数据通过Schema单独定义。 Schema通过、
apply(针对数组)和applyEach等函数应用到表单结构上。 这将数据的_结构_与管理它的_规则_分离开来。applyWhen -
指令作为桥梁:指令将DOM元素(原生输入框或自定义控件)与
[formField]绑定。 它负责:FieldNode- 同步DOM与Signal之间的值。
- 将状态(有效、已触碰等)反映到UI中。
- 处理用户交互事件(失焦、输入)。
Key Components
核心组件
1. FieldNode
(src/field/node.ts
)
FieldNodesrc/field/node.ts1. FieldNode
(src/field/node.ts
)
FieldNodesrc/field/node.tsThe central internal class representing a single field in the form graph. It aggregates several state managers:
- : Manages parent/child relationships and signal slicing.
structure - : Computes
validationState,valid,invalidsignals.errors - : Tracks
nodeState,touched,dirty.pristine - : Stores metadata like
metadataState,min,max.required - : Tracks submission status and server errors.
submitState
代表表单图中单个字段的核心内部类。它聚合了多个状态管理器:
- :管理父子关系和Signal切片。
structure - :计算
validationState、valid、invalid信号。errors - :跟踪
nodeState、touched、dirty状态。pristine - :存储
metadataState、min、max等元数据。required - :跟踪提交状态和服务器错误。
submitState
2. ValidationState
(src/field/validation.ts
)
ValidationStatesrc/field/validation.ts2. ValidationState
(src/field/validation.ts
)
ValidationStatesrc/field/validation.tsManages 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()
管理验证的复杂性:
- 同步错误:源自Schema规则。
- 异步错误:通过Signal处理,包括“pending(待处理)”状态。
- 树形错误:向上冒泡或针对特定字段的错误。
- 提交错误:通过命令式注入的服务器端错误。
submit()
3. FormField
Directive (src/directive/form_field_directive.ts
)
FormFieldsrc/directive/form_field_directive.ts3. FormField
指令(src/directive/form_field_directive.ts
)
FormFieldsrc/directive/form_field_directive.tsThe bridge between the and the DOM.
FieldNode- Selector:
[formField] - It supports:
- Native Elements: ,
<input>,<select>.<textarea> - Custom Controls: Components implementing or
FormUiControl.FormValueControl - Legacy Interop: Components implementing (via
ControlValueAccessor).InteropNgControl
- Native Elements:
FieldNode- 选择器:
[formField] - 支持:
- 原生元素:、
<input>、<select>。<textarea> - 自定义控件:实现或
FormUiControl接口的组件。FormValueControl - 遗留兼容:实现的组件(通过
ControlValueAccessor)。InteropNgControl
- 原生元素:
4. Schema
(src/api/structure.ts
& src/api/rules
)
Schemasrc/api/structure.tssrc/api/rules4. Schema
(src/api/structure.ts
& src/api/rules
)
Schemasrc/api/structure.tssrc/api/rulesDefines the behavior.
- Created via .
schema(fn) - Applied via .
apply(path, schema) - Rules include validators (,
required,pattern,min) and state modifiers (max,disabled).hidden
定义行为规则。
- 通过创建。
schema(fn) - 通过应用。
apply(path, schema) - 规则包括验证器(、
required、pattern、min)和状态修改器(max、disabled)。hidden
Data Flow
数据流
- Read: reads directly from the underlying signal (projected to the specific path).
form.field.value() - 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.
- 读取:直接从底层Signal读取(投影到特定路径)。
form.field.value() - 写入:向表单写入数据(例如通过UI)会更新底层Signal。
- 验证:一个计算效果会监听值Signal,并运行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">typescript
// 1. 定义模型
const user = signal({name: '', age: 0});
// 2. 定义Schema
const userRules = schema((u) => {
required(u.name);
min(u.age, 18);
});
// 3. 创建表单
const userForm = form(user, userRules); // 或 apply(userForm, userRules)
// 4. 在模板中绑定
// <input [formField]="userForm.name">Important Files
重要文件
- : Public API entry points (
packages/forms/signals/src/api/structure.ts,form).apply - : Interfaces for custom controls (
packages/forms/signals/src/api/control.ts).FormUiControl - : The
packages/forms/signals/src/field/node.tsimplementation.FieldNode - : The
packages/forms/signals/src/directive/form_field_directive.tsdirective.[formField]
- :公共API入口(
packages/forms/signals/src/api/structure.ts、form)。apply - :自定义控件的接口(
packages/forms/signals/src/api/control.ts)。FormUiControl - :
packages/forms/signals/src/field/node.ts的实现。FieldNode - :
packages/forms/signals/src/directive/form_field_directive.ts指令。[formField]
Supplemental Information
补充信息
- Compiler & Core Integration: Details how hooks into type-checking and the runtime.
[formField]
- 编译器与核心集成:详细介绍如何接入类型检查和运行时。
[formField]