皮影表单的两种使用模式
⚠️ 新手必读:Piying-View 提供两种使用模式,它们都基于 Valibot Schema 和
convertToField,但边界完全不同。请务必先分清你使用的是哪一种,避免混淆。
| 对比维度 | 模式一:自动模式(全自动渲染) | 模式二:手动模式(手动绑定) |
|---|---|---|
| 入口 | 组件 <piying-view> |
函数 convertToField() |
| 渲染方式 | 完全由库根据元数据自动渲染整棵组件树 | 你拿到 field 后手动绑定到原生控件 / 手动指定模板插入位置 |
| Schema 定义 | 通过 setComponent / fieldGlobalConfig 等元数据声明组件 |
同一套 Schema,但渲染位置由你决定 |
| 典型场景 | 标准表单、快速开发、字段完全跟随 Schema 定义 | 自定义布局、混合原生控件、局部插入字段、精细控制渲染位置 |
| 谁调用 convertToField | 库内部自动调用(你不需要手动调用) | 你自己调用,并持有返回的 field |
- 模式一:把决定权完全交给
<piying-view>组件,你只提供 Schema。 - 模式二:你亲手调用
convertToField(),拿到field后,用指令把它绑到某个控件或插入到某个模板位置。
模式一:自动模式(Schema 驱动 / 全元数据渲染)
Section titled “模式一:自动模式(Schema 驱动 / 全元数据渲染)”这是最常用、最省心的模式。你只需要在模板里放一个 <piying-view> 组件,传入 schema、model、options,其余全部交给库自动完成。
关键点:在自动模式里,你不需要手动调用
convertToField,直接用<piying-view>传schema/model/options即可。
自动模式的特性
Section titled “自动模式的特性”- 全元数据驱动:组件类型、输入、输出、包装器、隐藏/禁用、验证等全部由 Schema 中的 Actions(
setComponent/inputs/outputs/wrappers/hideWhen等)声明。 - 自动双向绑定:
[(model)]="model"自动同步数据。 - 自动递归:Group / Array 的子字段自动递归渲染,无需手动写循环。
- 自动套包装器:
actions.wrappers定义的包装器自动包裹每个字段。
模式二:手动模式(convertToField + 手动绑定)
Section titled “模式二:手动模式(convertToField + 手动绑定)”当你需要自定义布局、混用原生控件、或把字段插入到特定位置时,使用手动模式。
第一步:手动调用 convertToField 拿到 field
Section titled “第一步:手动调用 convertToField 拿到 field”convertToField() 返回一个 PiResolvedViewFieldConfig(field),它包含整棵字段树:表单控件(form.control)、子字段、组件定义、包装器、输入输出等。你拿到 field 后,有两种手动绑定方式。
关键点:
convertToField只负责解析,它本身不渲染任何东西。渲染位置完全由你通过指令决定。
手动绑定方式 A:绑定原生控件 — [formControl] 指令
Section titled “手动绑定方式 A:绑定原生控件 — [formControl] 指令”PiyingFieldControlBindDirective,选择器 [formControl]:
- 输入:
formControl(必填,PiResolvedViewFieldConfig)、path(可选KeyPath) - 把字段的
FieldControl暴露给原生表单控件,从而获得值双向绑定、验证、禁用状态。
⚠️ 被绑定的目标必须是 Angular 表单控件(带
NG_VALUE_ACCESSOR):
- 基础原生元素(
<input>、<select>、<textarea>等):Angular 官方自带这些基础绑定指令,只需导入FormsModule(或ReactiveFormsModule)即可,无需额外定义。- 自定义组件:必须自己实现
ControlValueAccessor并在 providers 中注册NG_VALUE_ACCESSOR,否则[formControl]无法识别。
自定义组件需自带 CVA 注册:
exportAs: 'formControl' 让你可以用模板引用变量拿到该 NgControl 做进一步操作:
注意:
[formControl]绑定的是叶子控件(FieldControl),所以如果目标字段是 Group/Array,会抛出🏷️ fieldControl❗错误。要绑定容器内部的某个叶子字段,用path定位。
手动绑定方式 B:插入模板位置 — [fieldTemplate] 指令
Section titled “手动绑定方式 B:插入模板位置 — [fieldTemplate] 指令”PiyingFieldTemplateDirective,选择器 [fieldTemplate]:
- 输入:
fieldTemplate(必填,PiResolvedViewFieldConfig)、path(可选KeyPath,不传则渲染整个根字段) - 把该字段的整棵组件树(组件 + 包装器 + 递归子字段)像自动模式一样渲染在当前位置。
「模板内是自动的」:[fieldTemplate] 只负责决定渲染位置,一旦指定了位置,该字段内部仍然走完整的自动渲染管线——组件的类型来自 Schema 元数据、包装器自动套用、Group 自动递归子字段。也就是说,手动模式只「手动」了外层位置,内层依旧全自动。
两种绑定方式的对比
Section titled “两种绑定方式的对比”| 方式 | 指令 | 渲染主体 | 适用场景 |
|---|---|---|---|
| A. 控件绑定 | [formControl] |
你写的原生控件(<input> 等) |
想用原生控件、完全自定义控件外观,但仍要获得值/验证/禁用能力 |
| B. 模板插入 | [fieldTemplate] |
库根据元数据自动渲染的组件 | 想指定字段的摆放位置,但字段组件本身仍由 Schema 决定 |
手动模式最小示例
Section titled “手动模式最小示例”把上面两种方式合在一起:k1 用 [formControl] 绑定原生 input(输入不足 3 个字符可看到验证错误);k2 用 [fieldTemplate] 插入,内部由 Schema 元数据自动渲染:
混合模式:两种模式互相嵌套
Section titled “混合模式:两种模式互相嵌套”💡 两种模式并非互斥,可以在同一页面互相嵌套。核心规律:
- 自动中用手动:在自动模式渲染的组件内部,用
[formControl]手动绑定字段到原生控件。- 手动中用自动:手动拿到
field后,用[fieldTemplate]绑定一个位置,该字段内部仍自动渲染。
自动中用手动 — 在自动渲染的组件内手动绑定字段
Section titled “自动中用手动 — 在自动渲染的组件内手动绑定字段”当你通过 setComponent 在 Schema 中注册一个自定义组件(自动模式),该组件内部依然可以用 [formControl] 手动绑定子字段、或用 [fieldTemplate] 摆放其他字段。
组件内通过 inject(PI_VIEW_FIELD_TOKEN) 获取当前字段:
在 Schema 中把它注册为根组件(自动模式):
组件模板内手动绑定子字段 k1,并用 [fieldTemplate] 自动渲染 k2:
这里 k1 是「自动中用手动」(在自动渲染的组件里,把字段手动绑到原生 input),k2 是「自动中套自动」(用 fieldTemplate 摆放位置,内部仍自动渲染)。
手动中用自动 — 手动模式下用 fieldTemplate 自动渲染
Section titled “手动中用自动 — 手动模式下用 fieldTemplate 自动渲染”在手动调用 convertToField 拿到 field 后,用 [fieldTemplate] 绑定一个插入位置,该字段内部(组件、包装器、递归子字段)全部走自动渲染:
fieldTemplate 的渲染管线和自动模式完全相同——你只负责位置,剩下的交给元数据。
混合模式速查
Section titled “混合模式速查”| 场景 | 入口 | 内部手段 | 效果 |
|---|---|---|---|
| 自动中用手动 | 自动模式组件内 | [formControl] 手动绑定字段 |
在自动渲染的组件里自定义原生控件 |
| 自动中套自动 | 自动模式组件内 | [fieldTemplate] 摆放字段 |
指定位置,内部自动渲染 |
| 手动中用自动 | convertToField 后 |
[fieldTemplate] 自动渲染 |
手动定位置,内层全自动 |
| 手动中用手动 | convertToField 后 |
[formControl] 绑定原生控件 |
完全手写控件但保留验证/值/禁用 |
什么时候用哪种模式?
Section titled “什么时候用哪种模式?”| 场景 | 推荐模式 |
|---|---|
| 标准表单、快速原型、字段完全跟随 Schema | 模式一(自动) |
| 需要完全自定义页面布局、混用原生控件 | 模式二(手动) |
| 只想把「某个字段」安放到特定位置,其余跟随 Schema | 模式二 B(fieldTemplate) |
只想用原生 <input>,但仍要验证/禁用/双向绑定 |
模式二 A(formControl) |
- 快速上手 — 自动模式完整示例
- 核心概念 — Schema → Field → Component 解析链
- Angular API 参考 —
PiyingView/PiyingFieldControlBindDirective/PiyingFieldTemplateDirective/convertToField - AbstractControl —
field.form.control控件操作