跳转到内容

asControl / asVirtualGroup

本文介绍 asControl()asVirtualGroup() 如何改变 Group/Intersect 类型的默认行为。

asControl — 将 Group 视为独立控件

Section titled “asControl — 将 Group 视为独立控件”

默认情况下,Piying-View 会将 v.object()v.array() 等容器类型展开为子字段的集合:

asControl() 让 Group/Array 类型的 Schema 不展开,而是作为一个独立的控件节点:

此时 address 对应一个 FieldControl 而非 FieldGroup,整个对象作为单个值处理。

场景一:将整个嵌套对象传递给自定义组件

当你的自定义组件需要接收整个嵌套对象(而不是逐个字段)时,使用 asControl()

const schema = v.object({
  profile: v.pipe(
    v.object({
      name: v.string(),
      age: v.number(),
    }),
    asControl(), // 作为独立控件
    setComponent('profile-editor'), // 自定义编辑器组件
  ),
});

// ProfileEditorComponent 接收整个 profile 对象

场景二:Union 类型作为单个控件

const schema = v.object({
  value: v.pipe(
    v.union([v.string(), v.number()]),
    asControl(), // 不展开为 logic group
    setComponent('value-input'), // 单一输入组件
  ),
});

场景三:Array 作为单个控件

const schema = v.object({
  items: v.pipe(
    v.array(v.string()),
    asControl(), // 整个数组作为一个值
    setComponent('array-editor'), // 自定义数组编辑器
  ),
});

asVirtualGroup — Intersect 子级作为虚拟 Group

Section titled “asVirtualGroup — Intersect 子级作为虚拟 Group”

默认情况下,v.intersect() 会被转换为 FieldLogicGroup。当需要在 intersect 内部保持 group 语义(而不是逻辑分组)时,使用 asVirtualGroup()

特性 asControl() asVirtualGroup()
作用对象 Group / Array / Union Intersect
默认行为 展开为子字段集合 FieldLogicGroup
使用后行为 作为单个 FieldControl 普通的 FieldGroup
返回类型 FieldControl FieldGroup
典型用途 将嵌套对象整体传给一个自定义组件 修改表单类型

v.intersect() + asVirtualGroup() 可以进行多级虚拟组,配合 tabs 组件实现标签页分组:

在保证数据结构正常的前提下,可通过 layout() 将字段移动到指定位置(priority 数字越小越靠前,keyPath 可引用 setAlias 设置的别名):

import * as v from 'valibot';
import { asControl, asVirtualGroup, layout } from '@piying/view-angular-core';

const schema = v.object({
  // Group 作为独立控件
  profile: v.pipe(v.object({ name: v.string(), age: v.number() }), asControl(), setComponent('profile-card')),

  // Intersect 子级作为虚拟 group
  settings: v.pipe(v.intersect([v.object({ theme: v.picklist(['light', 'dark']) }), v.object({ lang: v.picklist(['zh', 'en']) })]), asVirtualGroup()),

  // 嵌套使用:Intersect + Layout + asVirtualGroup
  content: v.pipe(v.intersect([v.pipe(v.object({}), layout({ priority: 1 })), v.pipe(v.object({}), layout({ priority: 2 }))]), asVirtualGroup()),
});