扩展内置 Form 引擎
Reactive Form 的内置引擎被封装在 Form
模型内,除了集成常用的成员类型, 还提供了一些帮助扩展成员类型的方法,以便于开发人员可以根据需要,丰富内置引擎的能力。 在本章中,我们将一起熟悉这些方法,并通过具体的示例来学习如何使用。
注册成员类型
在介绍 Reactive 的实现原理时, 我们提到过可以向 Reactive 实例中注册成员类型。 对于内置引擎而言,成员类型也是被注册到 Reactive 实例中, 不过,Form.install()
方法对 reactive#install()
方法进行了装饰, 提供了额外的能力,这些能力特性包括:
分组设定
在使用 Form.install()
注册内置引擎的成员类型时, 可以通过 group
属性对类型进行分组, 分组后的类型可通过 Form.group()
方法,按分组名称查询到注册时的配置。 当成员类型较多时,分组设定就为归类成员类型提供了帮助,我们通过下面的示例来具体说明。
引用范围设定
为了保证成员间引用的灵活性,Reactive DSL 在解析插值符中的引用路径时,并不对引用范围做限制,这意味着任何成员的任何属性间都可以产生引用。 对于一些表单引擎而言,成员的引用范围因输入项类型不同可能有所差异, 为了支持此类场景,Form
模型提供了设定成员引用范围的能力。
在使用 Form.install()
注册类型时, 可以通过 providers
属性对该类型成员的引用范围进行设定, 设定后可通过 Form.providers()
方法, 查询到该类型下某成员属性可引用的其它成员及属性范围。
基于这两个方法组合使用的能力,开发人员可以对不在范围内的引用进行适当的处理, 处理方式多种多样,并没有统一定论,比如,可以通过添加钩子函数, 向成员的存储空间中写入错误信息,或在产生引用的属性上进行过滤,甚至直接将产生引用的属性置空,等等。 下面,我们使用直接置空属性设定值的方式做例。
需要提及的一点是,对于注册时未设定 providers
的类型(如内置引擎默认集成的各输入项类型), 调用 Form.providers()
将返回默认引用范围。 默认可被引用的成员是所有 Fieldset
子级中含有 value
属性且不与被查询成员产生循环引用的成员, 默认可被引用的属性则是 value
。默认引用范围这样设定的原因是,大部分表单引擎中,成员属性的引用多发生在输入项的值之间。
另外, Form.providers()
方法在 Reactive Form 内置引擎配套的 UI 组件中,也起到了一定的辅助作用,后续的组件教程中将会介绍。
校验方法范围设定
在使用 Form.install()
注册类型时, 可以通过 validators
属性对可用于该类型成员的校验方法范围进行设定, 设定后可通过 Form.validators()
方法, 查询到该类型下某成员可用的校验方法。
与处理引用范围异常类似,组合使用这两个方法,可对成员属性包含不合规校验方法的情况, 进行适当的处理。下面,我们仍以直接置空属性设定值的方式做例。
对于注册时未设定 validators
的类型(如内置引擎默认集成的各输入项类型), 调用 Form.validators()
将返回默认的可用校验方法范围。 默认范围的匹配规则是,如果 schema
定义中 value
属性的 validation
指定了 dataType
, 则返回所有可用于该 dataType
的校验方法,否则只返回 presence
校验方法。
比如,内置引擎集成的 TextField
,其 schema
中对 value
属性的定义是:
{
prop: 'value',
validation: [{ dataType: 'String' }],
...otherDefinations
}
因为 validation
包含了 {dataType: 'String'}
,所以,调用 Form.validators()
查询 TextField
成员的可用校验方法范围,就会返回所有可应用于 String
数据类型的校验方法。
另外, Form.validators()
方法在 Reactive Form 内置引擎配套的 UI 组件中,也起到了一定的辅助作用,后续的组件教程中将会介绍。
计算方法范围设定
当前版本暂不提供设定成员属性计算规则范围的内置方法,后续版本中将逐渐添加。 现阶段,开发人员如有需求,可以先自行实现。
注册输入项类型
为了便于注册输入项类型,Form.Field
模型提供了,构建输入项类型配置对象的方法 Form.Field.schema.extend()
,还提供了可复用的 schema
配置以及钩子函数。 下面将介绍具体的使用方法。
复用 schema
在输入项类型的注册过程中,很多属性的 schema
定义都是雷同的, 比如标题数据类型为字符串、校验规则默认为空,等等。 Form.Field
内置了输入项类型常用的 schema
, 这些 schema
可通过 Form.Field.schema.use()
方法和 Form.Field.schema.extend()
方法直接复用或扩展后复用。 我们来看下面的示例。
通过示例可以看到,use
和 extend
这两个方法都会返回一个属性的 schema
定义。 这样,我们就可以在 schema.props
数组中,把不同属性的定义,按需拼装到一起了。 内置的 schema
属性范围包括 name
、label
、order
、value
、options
、placeholder
、editable
、visible
、 validation
、calculation
,读者可通过 use
方法查看它们的定义。
复用钩子函数
在介绍 Reactive 时,介绍过 Reactive
为了方便扩展, 内置了一些可复用的钩子函数。同样的,Form.Field
也内置了可复用的钩子函数, 这些钩子函数主要应用于输入项类型,可通过 Form.Field.hooks.use()
方法复用。 我们在下面的示例中将逐一展示这些钩子函数的作用和用法。
ENABLE_VALUE_CALCULATION
ENABLE_VALUE_CALCULATION
添加了输入项成员 calclation
属性和 value
属性的联动逻辑, 每当 calculation
当前值更新时,会使用该值设定 value
属性。具体用法如下例。
ENABLE_VALUE_VALIDATION
ENABLE_VALUE_VALIDATION
添加了输入项成员 validation
属性和 value
属性的联动逻辑, 每当 validation
当前值更新时或 value
当前值更新时,会使用前者校验后者,并清空或写入 value
错误信息。 具体用法如下例。
ENSURE_VALUE_WITHIN_OPTIONS
ENSURE_VALUE_WITHIN_OPTIONS
添加了输入项成员 options
属性和 value
属性的联动逻辑, 每当 options
当前值更新时或 value
当前值更新为非空值时,都会校验 value
是否在 options
范围内, 并清空或写入 value
错误信息。具体用法如下例。
Form.Field.hooks.default ()
当我们注册的输入项类型比较多以后,会发现有一些内置钩子函数的复用频率很高, 为了便于批量复用,Form.Field.hooks.default()
方法聚合了高频复用的钩子函数, 当该方法被调用时,会返回一个由这些钩子函数构成的数组,可以在注册输入项类型时直接使用。 其返回结果中包含的钩子函数按数组下标顺序依次为:
Reactive.hooks.use('BLOCK_INVALID_PARENT', {accept: 'Fieldset'})
Reactive.hooks.use('ENABLE_SCHEMA_DEFAULT')
Form.Filed.hooks.use('ENABLE_VALUE_CALCULATION')
Reactive.hooks.use('ENABLE_SCHEMA_VALIDATION')
Form.Filed.hooks.use('ENABLE_VALUE_VALIDATION')
开发人员可以在这些钩子函数基础上按需追加,对特定输入项类型的实现更多定制。
自动注册子表单输入项类型
在上一章,我们介绍过, 内置引擎集成的输入项类型经过自动化元编程处理后,可在子表单中嵌套。 这是因为内置引擎集成的输入项类型在注册前,使用 Form.Field.extend()
方法进行了装饰,装饰过程包括向 group
追加 Field
分组名称, 以便在注册时被识别,从而触发子表单输入项类型的生成过程,自动注册一个 Subform*Field
类型。
多数情况下我们希望自定义注册的输入项类型也可以嵌套进子表单, 那么就也可以使用 Form.Field.extend()
方法来装饰。 具体用法如下例。
小结
- 内置引擎中的成员默认可引用的是所有
Fieldset
子级中含有value
属性且不与自身产生循环引用的成员的value
属性。 - 内置引擎中的成员默认可用校验方法范围是,如果
schema
定义中value
属性的validation
指定了dataType
, 则为所有可用于该dataType
的校验方法,否则为presence
校验方法。 Form.Field
内置schema
可通过Form.Field.schema.use()
方法和Form.Field.schema.extend()
方法直接复用或扩展后复用。Form.Field
内置钩子函数可通过Form.Field.hooks.use()
方法复用。Form.Field.hooks.default()
方法聚合了注册输入项类型时高频复用的钩子函数。- 经
Form.Field.extend()
方法来装饰的输入项类型,在注册时会自动注册一个对应的子表单输入项类型。