antd-better-form
Happy to use antd-better-form in the project based on ant-design ^_^
在 ant-design 项目,使用 antd-better-form
来快速构建表单。支持所有的ant-design
输入型(data-entry
)组件。
github 及 更新日志 在 0.1.0 版本之前暂不开放, 如有问题或者建议可以发邮件咨询:jiangzhifeng666@163.com, 需备注:antd-better-form 问题咨询
安装 Installation
# npm
npm install antd-better-form --save
使用 Usage
先看一个使用示例:
import React from "react";
import { Form, FormItem } from "antd-better-form";
import { Input, message } from "antd"; // 导入antd的Input组件
const MyForm = () => {
return (
<Form layout="inline">
{$form => {
const { $params, $valid, $reset, $getFirstError } = $form;
const onSubmit = () => {
if ($valid) {
// submit your codes
} else {
message.error($getFirstError());
}
};
return (
<>
<FormItem
name="username"
itemProps={{
label: "Username"
}}
>
<Input />
</FormItem>
<Button
style={{ marginRight: "12px" }}
type="primary"
onClick={onSubmit}
>
确定
</Button>
<Button onClick={$reset}>重置</Button>
</>
);
}}
</Form>
);
};
如果你觉得上面的方式不够优雅,你也可以使用withForm
:
import React from "react";
import { withForm, FormItem } from "antd-better-form";
import { Input, message } from "antd"; // 导入antd的Input组件
const MyForm = ({ $form }) => {
const { $params, $valid, $reset, $getFirstError } = $form;
const onSubmit = () => {
if ($valid) {
// submit your codes
} else {
message.error($getFirstError());
}
};
return (
<div>
<FormItem
name="username"
itemProps={{
label: "Username"
}}
>
<Input />
</FormItem>
<Button style={{ marginRight: "12px" }} type="primary" onClick={onSubmit}>
确定
</Button>
<Button onClick={$reset}>重置</Button>
</div>
);
};
export default withForm(MyForm);
FormItem
是 antd-better-form
新增加的组件
只需要将ant-design
的交互组件,嵌套在FormItem
下,即可实现自动的表单状态同步。
withForm(Component)
withForm
是基于 Form 封装的高阶组件,withForm 的第二个参数为可选配置,如果定义了该参数,会将配置传递给 Form 组件。
const FormComp = () => {
// ...
};
export default withForm(FormComp, {
layout: "horizontal" //该项将传递给Form组件
});
withForm
同样支持装饰器语法
@withForm
class MyField extends Component {}
//or pass some default props
@withForm({
layout: "inline"
})
class MyField extends Component {}
<Form />
支持传递的属性
$defaultValues
全局统一设置表单的默认值,不在需要在每个表单上设置单独$defaultValue
。如果你两个地方都设置了同一个 FormItem 的默认值, $defaultValue 的优先级要高于 $defaultValues, 这也符合就近向上寻找的原则。
<Form $defaultValues={name: "ghostjzf"}>
或者
withForm(MyFormComp, {
$defaultValues: {
name: "ghostjzf"
}
})
layout
表单布局, horizontal
、vertical
、inline
, 默认值:horizontal
hideRequiredMark
隐藏所有表单项的必选标记, 默认值:false
labelAlign
label 标签的文本对齐方式, left
、right
, 默认值:right
labelCol
ant-design
(3.14.0 新增,之前的版本只能设置到 FormItem 上。)label 标签布局,同
wrapperCol
ant-design
(3.14.0 新增,之前的版本只能设置到 FormItem 上。)需要为输入控件设置布局样式时,使用该属性,用法同 labelCol
colon
配置 Form.Item 的 colon 的默认值 (只有在属性 layout 为 horizontal 时有效)
$form
$form
是当你是用withForm
或是 <Form />
时为子组件注入的 props, 其中$form 包含以下参数:
$params
表单搜集的值的集合$valid
|$invalid
,$valid
在表单项所有的表单项为合法的时候值为 true, 否则为 false.$invalid
的值和$valid
相反。$getFirstError
获取表单项第一项错误$reset
类型:Func, 重置表单,重置回默认值, 如果$reset传入参数,例如$reset('filedName')可以重置指定项的 value 值$getField
获取指定表单项的工具, 包括:$setValue
$reset
$form.$getField("name").$setValue("ghostjzf"); // 设置值
$form.$getField("name").$reset(); // 重置回默认值
<FormItem />
要实现将ant-design
的交互组件的值能同步到 antd-better-form 的状态中,需要通过 FormItem 这个组件来实现中间态绑定。
它的作用有些类似 antd 中的getFieldDecorator
方法,但是用法比getFieldDecorator
更优雅,更 JSX 语法。FormItem
完全是标签声明式用法,它是对 antd 的Form.Item
组件的再次封装。
所以FormItem
会完整实现Form.Item
所可以显示的校验状态、错误暂时等 UI 变化。
如果给
FormItem
传递了多个子节点,则只会对第一个节点进行表单状态绑定!!
支持传递的属性
required
是否必填,默认值: false
name
设置输入项的 name 值,表单项将会以 name 作为 key 收集到 $form 的状态中.
$defaultValue
设置该表单项的默认值
$onChange
当 FormItem 的值发生变化时发生的回调
<FormItem
$onChange={value => {
console.log(value)
}}
itemProps={{
label: "Username"
}}
>
<Input />
</FormItem>
validMessage
内置 required 错误提示信息
$validators
自定义设置校验方法, 返回错误提示信息,会覆盖 validMessage。
<FormItem $validators={value => {
if (XXX) {
return "XXX is valid"
}
}}>
itemProps
该属性为要传递给Form.Item
组件的配置项:
label
label 标签的文本, 类型string
colon
。配合 label 属性使用,表示是否显示 label 后面的冒号, 默认值true
hasFeedback
配合 validateStatus 属性使用,展示校验状态图标,建议只配合 Input 组件使用,默认值false
htmlFor
设置子元素 label htmlFor 属性, 类型string
labelCol
label 标签布局,同 组件,设置 span offset 值,如 {span: 3, offset: 12} 或 sm: {span: 3, offset: 12}。在 3.14.0 之后,你可以通过 Form 的 labelCol 进行统一设置。当和 Form 同时设置时,以 FormItem 为准。wrapperCol
需要为输入控件设置布局样式时,使用该属性,用法同 labelCol。在 3.14.0 之后,你可以通过 Form 的 wrapperCol 进行统一设置。当和 Form 同时设置时,以 FormItem 为准。labelAlign
标签文本对齐方式,left
、right
, 默认值:right
<FormItem
itemProps={{
label: "Username",
colon: false
}}
>
<Input />
</FormItem>
$parser
当用户在表单中进行输入时(主动更新视图),视图中的值在更新到状态模型中前,会经过 $parser 处理。
// 例如可以通过$parser属性来过滤前后输入空格
<FormItem name="fieldName" $parser={(value) => value.trim()}>
//...
</FormItem>
注意,上述写法不会修改当前视图值,它仅仅影响状态模型中的值。
$formatter
表单初次渲染时更新视图的函数
例如当你需要在视图中默认带一个货币前缀时
<FormItem name="fieldName" $formatter={(value) => `¥${value}`}>
//...
</FormItem>
valuePropName
`changePropName
可以用来设置绑定到组件上的值或者值变动的事件回调。该项一般不需要设置,FormItem 已经针对 antd 中的所有 data-entry 型组件做了兼容处理。
支持的组件
AutoComplete
<FormItem
name="autoComplete"
itemProps={{
label: "AutoComplete输入框"
}}
>
<AutoComplete />
</FormItem>
Checkbox
支持Checkbox.Group
。
<FormItem
name="isChecked2"
$defaultValue={["A", "C"]}
itemProps={{
label: "Check Group",
}}
>
<Checkbox.Group>
<Checkbox value="A">A</Checkbox>
<Checkbox value="B">B</Checkbox>
<Checkbox value="C">C</Checkbox>
</Checkbox.Group>
</FormItem>
Cascader
DatePicker
DatePicker
TimePicker
DatePicker.WeekPicker
DatePicker.MonthPicker
DatePicker.RangePicker
等几个日期类组件,都是深度结合了moment
使用的。如果希望收集到表单中的值是格式化好的时间字符串,可以通过$parser
$formatter
实现:
<FormItem
name="datepicker"
$parser={moment => moment.format("YYYY-MM-DD")}
$formatter={date => moment(date)}
>
<DatePicker />
</FormItem>
对于DatePicker.RangePicker
,由于其值是一个数组,所以需要这样处理:
<FormItem
name="datepicker"
$parser={moments => moments.map(moment => moment.format("YYYY-MM-DD"))}
$formatter={dates => dates.map(date => moment(date))}
>
<DatePicker.RangePicker />
</FormItem>
InputNumber
<FormItem
name="inputNumber"
itemProps={{
label: "InputNumber数字框"
}}
>
<InputNumber />
</FormItem>
Input
Mention
Rate
<FormItem
name="rate"
$defaultValue={2.5}
itemProps={{
label: "Rate"
}}
>
<Rate allowHalf />
</FormItem>
Radio
支持Radio.Group
。
<FormItem
name="radio"
$defaultValue="B"
itemProps={{
label: "Radio"
}}
>
<Radio.Group>
<Radio value="A">A</Radio>
<Radio value="B">B</Radio>
<Radio value="C">C</Radio>
</Radio.Group>
</FormItem>
Switch
Switch
Checkbox
(不包括Checkbox.Group
) Radio
(不包括Radio.Group
)三个组件,可以通过给FormItem
传递$defaultValue={true}设置默认值:
<FormItem $defaultValue={true}>
<Switch />
</FormItem>
Slider
<FormItem
name="slider"
$defaultValue={50}
itemProps={{
label: "Slider进度条"
}}
>
<Slider />
</FormItem>
Select
<FormItem
name="select"
$defaultValue="lucy"
itemProps={{
label: "Select下拉框"
}}
>
<Select style={{ width: 200 }}>
<Select.Option value="jack">Jack</Select.Option>
<Select.Option value="lucy">Lucy</Select.Option>
<Select.Option value="disabled" disabled>
Disabled
</Select.Option>
<Select.Option value="Yiminghe">yiminghe</Select.Option>
</Select>
</FormItem>
TreeSelect
<FormItem
name="treeSelect"
itemProps={{
label: "TreeSelect下拉框"
}}
>
<TreeSelect
multiple
showSearch
style={{ width: 300 }}
dropdownStyle={{
maxHeight: 400,
overflow: "auto"
}}
placeholder="Please select"
allowClear
treeDefaultExpandAll
>
<TreeNode value="parent 1" title="parent 1" key="0-1">
<TreeNode value="parent 1-0" title="parent 1-0" key="0-1-1">
<TreeNode value="leaf1" title="my leaf" key="random" />
<TreeNode value="leaf2" title="your leaf" key="random1" />
</TreeNode>
<TreeNode value="parent 1-1" title="parent 1-1" key="random2">
<TreeNode
value="sss"
title={
<b
style={{
color: "#08c"
}}
>
sss
</b>
}
key="random3"
/>
</TreeNode>
</TreeNode>
</TreeSelect>
</FormItem>
Transfer
TimePicker
Upload
Upload
组件会将 onChange 回调的对象同步到表单状态中,所以如果仅仅需要拿到上传成功后的服务端返回信息(比如上传后保存在服务器的 url),可以通过$parser 进行过滤:
<FormItem
name="upload"
$parser={({ file, fileList, event }) => {
if (file.status == "done") {
//render url form server
return JSON.parse(file.response).data.url;
}
}}
>
<Upload {...uplodConfig}>
<Button>
<Icon type="upload" /> Click to Upload
</Button>
</Upload>
</FormItem>
FAQ
在生产环境(NODE_ENV==='production')部分组件调用有异常?
如果在生产环境,发现例如Checkbox
Radio
Switch
等组件无法正确捕获用户输入的值,这种情况一般是由于项目中使用了babel-plugin-import
插件。
antd-better-form
中是使用 import { Switch } from 'antd'
这种写法来调用 Switch
组件的,而babel-plugin-import
插件会将项目源代码中的类似语句,替换成import Switch from 'antd/lib/switch'
。这两种写法获取到的Switch
其实并不是严格意义上的相等,前者是对后者的又一层导出封装。
而由于babel-plugin-import
一般仅仅会配置成仅仅对项目代码进行处理,所以处于项目node_modules
目录中的antd-better-form
中的语句不会被处理。我们需要通过修改项目 webpack 配置的方式,来使babel-plugin-import
插件能处理antd-better-form
的代码。
可以编辑项目的 webpack 配置(只需要配置生产环境的构建配置即可),在rules
模块下添加以下的代码:
{
test: /\.(js|mjs)$/,
include: /react-antd-formutil/, // 仅仅处理react-antd-formutil即可
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
plugins: [[
"import",
{
"libraryName": "antd"
},
"antd"
]]
}
}