Skip to content

qiqiboy/react-mui-formutil

Repository files navigation

react-mui-formutil

npm peerDependencies definitionTypes gzip download issues license github github github github

Happy to use react-formutil in the project based on @mui/material ^_^

@mui/material 项目,结合react-formutil 来快速构建表单。

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

  1. ant-design react-antd-formutil npm
  2. react-bootstrap react-bootstrap-formutil npm
  3. react-md react-md-formutil npm

安装 Installation

react-mui-formutil

# npm
npm install react-mui-formutil --save

# yarn
yarn install react-mui-formutil

使用 Usage

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

import React, { Component } from 'react';
import { withForm, FormControl, $Formutil } from 'react-mui-formutil';
import { Box, TextField } from '@mui/material'; // 导入mui的TextField组件

interface MyFormProps {
    $formutil: $Formutil;
}
const MyForm: React.FC = () => {
    const onSubmit = ev => {
        ev.preventDefault();

        // ...
    };

    return (
        <Box component="form" noValidate onSubmit={onSubmit}>
            <FormControl label="Username" name="username" fullWidth>
                <TextField />
            </FormControl>

            <Button fullWidth type="submit">
                submit
            </Button>
        </Box>
    );
};

export default withForm(MyForm);

FormControlreact-mui-formuitl 中提供的用于标单项交互的组件,withFormreact-formutil的组件(没错,你可以直接从react-material-formutil中导出react-formutil的组件啦)。

只需要将@mui/material的表单类组件,嵌套在FormControl下,即可实现自动的表单状态同步。

<FormControl />

要实现将@mui/material的表单组件的值能同步到 react-formutil 的状态中,需要通过 FormControl 这个组件来实现中间态绑定。

FormControl类似@mui/material中的同名组件,但是它基于react-formutil实现了表单状态的收集与同步。你应当在react-formutil表单中总是使用这个新的FormControl

FormControl下只允许放置一个表单组件,不允许多个。

name

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

label

设置 label,你也可以传入Typography或者其他节点对象以实现 label 样式自定义。

<FormControl name="name" label="Username">
    <TextField />
</FormControl>

// 如果要自定义label的样式,可以这样:
<FormControl name="name" label={<Typography variant="h5" sx={{ mb:1 }}>Username</Typography>}>
    <TextField />
</FormControl>
helperText

设置 helperText,你也可以直接传递各类节点对象以实现样式自定义。

<FormControl name="name" helperText="Please type your name">
    <TextField />
</FormControl>

//or

<FormControl name="name" helperText={<Box component="span" sx={{ fontWeight: 700 }}>Please type your name</Box>}>
    <TextField />
</FormControl>
noStyle

noStyle可以用来控制是否输出FormControl的额外的样式元素。缺省情况下默认值为false。这在一些需要组合使用的场景下非常有用!

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

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

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

  1. 最外层的FormControl不能设置name属性,否则将不会被当作子级的校验状态容器
  2. 内层的FormControl需要添加相应的name值(向表单控制器注册自身)以及noStyle属性(不渲染额外的样式,避免和上层冲突)
// 这里不能设置name
<FormControl label="姓名">
    <Grid container spacing={2}>
        {/* 与普通的FormControl用法一致,只是多了个noStyle */}
        <Grid item xs={6}>
            <FormGroup name="first_name" required validMessage={{ required: 'First name reuqired!' }} noStyle>
                <TextField label="姓" />
            </FormGroup>
        </Grid>
        <Grid item xs={6}>
            <FormGroup name="last_name" required validMessage={{ required: 'Last name reuqired!' }} noStyle>
                <TextField label="名" />
            </FormGroup>
        </Grid>
    </Grid>
</FormControl>

以上运行示例请参考 示例 demo4

$defaultValue

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

$validators

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

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

  • 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 匹配错误信息。

$parser

设置输入的值收集到 formutil 状态中时的过滤处理。默认为value => value

<FormControl $parser={value => parseInt(value)}>
    <Input />
</FormControl>
$formatter

设置 formutil 中的值渲染到输入组件上时的过滤处理。默认为value => value

<FormControl $formatter={value => '$' + value}>
    <Input />
</FormControl>
checked unchecked

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

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

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

validMessage

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

<FormControl
    name="username"
    required
    validMessage={{
        required: '请输入用户名'
    }}>
    <Input />
</FormControl>
$validateLazy

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

valuePropName changePropName focusPropName blurPropName

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

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

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

请参考 getValueFromEvent()

errorLevel

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

<CheckboxGroup />

@mu/material 提供了RadioGroup组件,但是却并没有提供相应的CheckboxGroup。所以,它来了。

<FormControl name="checkboxgroup" required label="Checkbox group">
    <CheckboxGroup>
        <FormControlLabel value="apple" control={<Checkbox />} label="Apple" />
        <FormControlLabel value="peach" control={<Checkbox />} label="Peach" />
    </CheckboxGroup>
</FormControl>

setErrorLevel(level)

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

  • 0$dirty $touched invalid 都为 true 时
  • 1$dirty invalid 都为 true 时
  • 2invalid 为 true 时

默认值为 1

import { setErrorLevel } from 'react-antd-formutil';

setErrorLevel(0);

支持的组件

需要注意的是,日期、时间选择器组件的valueonChange的 ts 类型声明为必须,但是实际在配合react-mui-formutil使用时是无需指定的。为了避免报错,可以指定最小空值即可:

<FormControl name="datepicker.datepicker" required fullWidth sx={{ mb: 2 }}>
    <DatePicker value={null} onChange={() => {}} label="DatePicker" renderInput={params => <TextField {...params} />} />
</FormControl>