Have ideas to improve npm?Join in the discussion! »

    react-antd-formutil
    TypeScript icon, indicating that this package has built-in type declarations

    1.1.13 • Public • Published

    react-antd-formutil

    npm peerDependencies definitionTypes gzip download issues license github github github github

    react-antd-formutil

    Happy to use react-formutil in the project based on ant-design@3&4 ^_^

    ant-design 项目,结合 react-formutil 来快速构建表单。支持所有的ant-design输入型(data-entry)组件。

    如果你在使用其他 react 组件库,可以查阅:

    1. react-bootstrap react-bootstrap-formutil npm
    2. react-md react-md-formutil npm
    3. Material-UI react-material-formutil npm

    安装 Installation

    react-antd-formutil

    react-antd-formutil1.0.0版本开始,同时支持 Ant Design 3.x4.x版本

    # npm
    npm install react-antd-formutil --save
    
    # yarn
    yarn install react-antd-formutil

    使用 Usage

    react-antd-formutil 整合了 react-formutil 的组件,所以可以直接从react-antd-formutil中导出所需要的 react-formutil 组件。不用单独从 react-formutil 中导出。

    先看一个使用示例(点击查看在线完整示例: react-antd-formutil on codesandbox.io):

    import React, { Component } from 'react';
    import { withForm, FormItem } from 'react-antd-formutil';
    import { Input, Form } from 'antd'; // 导入antd的Input组件
    
    @withForm
    class MyForm extends Component {
        submit = () => {
            const { $invalid, $getFirstError, $params } = this.props.$formutil;
    
            if ($invalid) {
                alert($getFistError());
            } else {
                // submit your data
            }
        };
    
        render() {
            return (
                <Form onSubmit={this.onSubmit}>
                    <FormItem
                        name="username"
                        itemProps={{
                            label: 'Username'
                        }}>
                        <Input />
                    </FormItem>
                </Form>
            );
        }
    }

    FormItemreact-antd-formuitl 新增加的组件,withFormreact-formutil的组件(没错,你可以直接从react-antd-formutil中导出react-formutil的组件啦)。

    只需要将ant-design的交互组件,嵌套在FormItem下,即可实现自动的表单状态同步。

    <FormItem />

    要实现将ant-design的交互组件的值能同步到 react-formutil 的状态中,需要通过 FormItem 这个组件来实现中间态绑定。

    它的作用有些类似 antd 中的getFieldDecorator方法,但是用法比getFieldDecorator更优雅,更 JSX 语法。FormItem完全是标签声明式用法,它是对 antd 的Form.Item组件的再次封装。

    所以FormItem会完整实现Form.Item所可以显示的校验状态、错误暂时等 UI 变化。

    如果给 FormItem 传递了多个子节点,可能会出现无法非预期的异常情况。你可以了解如何正确的使用FormItem嵌套渲染多个节点元素?

    支持传递的属性

    FormItem可以接收所有antd中的Form.Item组件所接收的所有属性,另外还新增以下属性支持:

    name

    设置输入项的 name 值,表单项将会以 name 作为 key 收集到 formutil 的状态中。支持嵌套语法 (同react-formutilField同名参数,可以参考 name

    $defaultValue

    设置该表单项的默认值 (同react-formutilField同名参数,可以参考$defaultvalue

    $validators

    设置校验方法 (同react-formutilField同名参数, 可以参考 $validators

    同 react-formutil 的 EasyField,FormItem 也内置了同样的校验规则:

    • required 必填 required
    • maxLength 。最大输入长度,有效输入时才会校验 maxLength="100"
    • minLength 最小输入长度,有效输入时才会校验 minLength="10"
    • max 最大输入数值,仅支持 Number 比较。有效输入时才会校验 max="100"
    • min 最小输入数值,仅支持 Number 比较。有效输入时才会校验 min="10"
    • pattern 正则匹配。有效输入时才会校验 pattern={/^\d+$/}
    • enum 枚举值检测。有效输入时才会校验 enum={[1,2,3]}
    • checker 自定义校验函数。checker={value => value > 10 && value < 100 || '输入比如大于10小与100'}

    注:校验属性的值为 null 时表示不进行该校验

    内置的校验规则无需再次声明,除非规则不符合预期,需要替换,则可以通过$validators 传递同名校验方法即可替换默认的。另外,内置的校验规则,如果校验不通过,会尝试去 validMessage 匹配错误信息。

    itemProps

    该属性为要传递给Form.Item组件的配置项:

    <FormItem
        itemProps={{
            label: 'Username',
            colon: false
        }}>
        <Input />
    </FormItem>
    $parser

    请参考react-formutil$parser介绍。

    $formatter

    请参考react-formutil$formatter介绍。

    checked unchecked

    对于 <Switch /> <Checkbox /> <Radio /> 这三种组件,其值默认是 checked 属性,为布尔值。可以通过checked unchecked来设置 checked 状态时所要映射的值:

    <FormItem checked="yes" unchecked="no">
        <Switch />
    </FormItem>

    该示例中, 当 Switch 为开时,获取的值将为 yes。

    $validateLazy

    可以用来优化表单的校验速度,请参考: $validateLazy

    $memo

    可以用来优化当前表单项的性能,避免过多的重复渲染。如果你遇到了表单性能问题,可以尝试该属性来改善。

    详细解释和使用、注意事项请参考: $memo

    validMessage

    设置校验结果的错误信息。

    <FormItem
        name="username"
        required
        validMessage={{
            required: '请输入用户名'
        }}>
        <Input />
    </FormItem>
    valuePropName changePropName focusPropName blurPropName

    该四个参数可以用来设置绑定到组件上的值或者值变动、是否聚焦等事件回调。该项一般不需要设置,FormItem 已经针对 antd 中的所有 data-entry 型组件做了兼容处理。

    对于一些特殊场景,例如不需要同步 focusblur,则可以通过将该值设为{null}来禁用:

    //禁用focus、blur状态同步
    <FormItem focusPropName={null} blurPropName={null} name="username">
        <Input />
    </FormItem>
    getValueFromEvent

    请参考 getValueFromEvent()

    noStyle

    该属性从 v1.1.0 起可用

    该属性同时兼容antd@3.xantd@4.x,都可以使用!

    noStyleAntDesign v4.0中新版本的Form.ItemnoStyle类似,可以用来控制是否输出Form.Item的额外的样式元素。缺省情况下默认值为false

    noStyletrue时,将会只渲染字段节点本身,但是其表单状态依然会被处理收集。此时,如果其存在父级嵌套的FormItem,那么其表达校验状态将会传递给父级的FormItem来展现。

    这对于连续的紧凑型表单元素将非常有用!可以避免校验错误描述信息都堆叠在一起! 但是没有额外的样式显示,包括表单校验状态都无法显示了。此时可以在其外层包裹一层不带nameFormItem,这些noStyle的表单项就会把他们自身的状态向上进行注册显示了!

    但是有以下几点需要注意:

    1. 最外层的FormItem不能设置name属性,否则将不会被当作子级的校验状态容器
    2. 内层的FormItem需要添加相应的name值(向表单控制器注册自身)以及noStyle属性(不渲染额外的样式,避免和上层冲突)
    // 这里不能设置name
    <FormItem label="FormItem Group">
        <Input.Group compact>
            {/* 与普通的FormItem用法一致,只是多了个noStyle */}
            <FormItem name="address.province" noStyle required validMessage={{ required: 'Province requird!' }}>
                <Select placeholder="Select province">
                    <Select.Option value="Zhejiang">Zhejiang</Select.Option>
                    <Select.Option value="Jiangsu">Jiangsu</Select.Option>
                </Select>
            </FormItem>
    
            <FormItem name="address.street" noStyle required validMessage={{ required: 'Street requird!' }}>
                <Input style={{ width: '50%' }} placeholder="Input street" />
            </FormItem>
        </Input.Group>
    </FormItem>

    以上运行示例请参考 示例

    errorLevel

    用来覆盖全局的 errorLevel 设置。参考setErrorLevel(level)

    setErrorLevel(level)

    setErrorLevel 该方法可以用来全局设置错误信息何时出现,有三个级别可以设置:

    • 0$dirty $touched $invalid 都为 true 时
    • 1$dirty $invalid 都为 true 时
    • 2$invalid 为 true 时
    • off 关闭错误显示

    默认值为 1

    注意,该方法影响全局,如果只是希望单独对某个表单项进行设置,可以通过errorLevel属性进行设置:参考errorLevel

    import { setErrorLevel } from 'react-antd-formutil';
    
    setErrorLevel(0);
    
    // 当关闭错误显示时,errorLevel='off',你可以手动自行设置错误展示方式:
    <FormGroup
        name="errorOff"
        errorLevel="off"
        itemProps={{
            validateStatus: $formutil.$errors.errorOff ? 'error' : undefined,
            help: $formutil.$errors.errorOff ? <div>出错啦</div> : null
        }}>
        <Input />
    </FormGroup>;

    支持的组件

    AutoComplete
    Checkbox

    支持Checkbox.Group

    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
    Input
    Mentions
    Pagination

    Pagination 并非antd所归纳的data entry组件,但是其接口设计也可以支持FormItem

    <FormItem name="page" $defaultValue={2}>
        <Pagination pageSize={10} total={100} />
    </FormItem>
    Rate
    Radio

    支持Radio.Group

    Switch

    Switch Checkbox(不包括Checkbox.Group) Radio(不包括Radio.Group)三个组件,可以通过给FormItem传递checked unchecked属性来改变被勾选时所映射到表单状态中的值:

    <FormItem checked="yes" unchecked="no">
        <Switch />
    </FormItem>
    Slider
    Select
    TreeSelect
    Transfer

    Transfer收集到表单状态中的是targetKeys

    TimePicker

    参考 DatePicker

    Upload

    Upload组件非常特殊,其接受fileList对象作为整个组件的状态。而实际业务中,往往只需要获取上传文件的返回的地址,或者一组文件的地址。可以通过$parser控制如何获取上传结果的值,并且可以通过$parser的第二个回调方法$setViewValue来控制fileList对象,实现对文件上传数量的控制。

    单个文件上传,获取单个文件上传地址

    <FormItem
        name="upload"
        $formatter={url =>
            url && [
                {
                    url,
                    uid: url,
                    status: 'done',
                    name: url.split('/').slice(-1)[0]
                }
            ]
        }
        $parser={(info, $setViewValue) => {
            // 必不可少,限制只能上传一个文件
            $setViewValue(info.fileList.slice(-1));
    
            if (info.file.status === 'done') {
                return info.file.response.url;
            }
        }}
        itemProps={{ ...formItemLayout, label: 'Upload' }}
        required>
        <Upload {...uplodConfig}>
            <Button>
                <UploadOutlined /> Click to Upload
            </Button>
        </Upload>
    </FormItem>

    多文件列表上传,获取多个文件上传地址数组

    <FormItem
        name="upload"
        $formatter={urls =>
            urls &&
            urls.map(url => ({
                url,
                uid: url,
                status: 'done',
                name: url.split('/').slice(-1)[0]
            }))
        }
        $parser={(info, $setViewValue) => {
            // 限制最大上传文件数量为3,如果不需要限制,可以移除该行,或者修改该值
            $setViewValue(info.fileList.slice(-3));
    
            return info.fileList.filter(file => file.status === 'done').map(file => file.url || file.response.url);
        }}
        itemProps={{ ...formItemLayout, label: 'Upload' }}
        required>
        <Upload {...uplodConfig}>
            <Button>
                <UploadOutlined /> Click to Upload
            </Button>
        </Upload>
    </FormItem>

    动态className

    FormGroup会自动给表单节点增加与该表单项校验状态相关的 className:

    • has-error
    • is-invalid
    • is-valid
    • is-touched
    • is-untouched
    • is-focused
    • is-unfocused
    • is-dirty
    • is-pristine

    FAQ

    给组件设置的onChange、onFocus等方法无效、不执行

    FormItem会覆盖掉直接添加到 antd 组件上的onFocus onBlur onChange方法,所以如果需要这三个事件方法,需要添加到 FormItem上:

    <FormItem name="test" onChange={ev => console.log('change', ev)} onFocus={ev => console.log('focus', ev)}>
        <Input />
    </FormItem>

    RangePicker 在safari下假死?

    经过 debug,在3.8.x版本上,依然存在对RangePicker设置onFocus onBlur会异常频繁触发(比如在光标经过日期选择面板中每个数字时)的问题。可以禁用onFocus onBlur状态同步:

    <FormItem name="datepicker" focusPropName={null} blurPropName={null}>
        <DatePicker.RangePicker />
    </FormItem>

    在生产环境(NODE_ENV==='production')部分组件调用有异常?

    如果在生产环境,发现例如Checkbox Radio Switch等组件无法正确捕获用户输入的值,这种情况一般是由于项目中使用了babel-plugin-import插件。

    react-antd-formutil中是使用 import { Switch } from 'antd' 这种写法来调用 Switch 组件的,而babel-plugin-import插件会将项目源代码中的类似语句,替换成import Switch from 'antd/lib/switch'。这两种写法获取到的Switch其实并不是严格意义上的相等,前者是对后者的又一层导出封装。

    而由于babel-plugin-import一般仅仅会配置成仅仅对项目代码进行处理,所以处于项目node_modules目录中的react-antd-formutil中的语句不会被处理。我们需要通过修改项目 webpack 配置的方式,来使babel-plugin-import插件能处理react-antd-formutil的代码。

    可以编辑项目的 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"
            ]]
        }
    }

    如何正确的使用FormItem嵌套渲染多个节点元素?

    你可以通过给给children属性传递render props函数,来自由定义要渲染出的节点。但是请注意,当传递一个render props函数时,需要手动绑定相关绑定事件和 value 属性!

    children函数接受一个$fieldHandler的对象,默认情况下其包含value onChange onFocus onBlur四个属性,但是如果你给FormItem传递了valuePropName等属性的话,这个值将会变为你通过valuePropName所定义的名字。

    更具体解释可以参考 react-formutil.$fieldHandler

    <FormItem name="username">
        {$fieldHandler => (
            <>
                <Input {...$fieldHandler} />
                <div>其它节点内容</div>
            </>
        )}
    </FormItem>

    Install

    npm i react-antd-formutil

    DownloadsWeekly Downloads

    68

    Version

    1.1.13

    License

    ISC

    Unpacked Size

    147 kB

    Total Files

    21

    Last publish

    Collaborators

    • avatar