@uiw-admin/components
Version:
1,386 lines (1,321 loc) • 39 kB
Markdown
# ProForm 表单
基于[uiw Form](https://uiwjs.github.io/#/components/form)封装。
- ✅ 支持原uiw/Form的提交方式并可以更简洁的生成表单
- ✅ 支持多个表单同时提交
- ✅ 支持动态添加表单
- ✅ 支持只读模式表单
## 何时使用
- 用于创建一个实体或收集信息。
- 需要对输入的数据类型进行校验时。
<!--ProForm-->
## 类型
> 通过formType表单类型
### 卡片类型
```jsx mdx:preview
import React from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
const Demo = () => {
return (
<div>
<ProForm
title="卡片表单"
formType="card"
onChange={(initial, current) => {
console.log('onChange', initial, current);
}}
colProps={{span:12}}
formDatas={ [
{
label: 'input',
key: 'input',
widget: 'input',
initialValue: '',
widgetProps: {},
},
{
label: 'radio',
widget: 'radio',
key: 'radio',
widgetProps: {
disabled: false
},
option: [
{ label: '男', value: 'man' },
{ label: '女', value: 'girl' }
],
},
]}
/>
</div>
);
}
export default Demo
```
### 折叠类型
```jsx mdx:preview
import React from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
const Demo = () => {
return (
<div>
<ProForm
title="折叠表单"
formType="collapse"
formDatas={ [
{
label: 'input',
key: 'input',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"24",
},
]}
/>
</div>
);
}
export default Demo
```
### 纯表单类型
> pure类型下将不再展示title
```jsx mdx:preview
import ReactDOM from 'react-dom';
import React from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
const Demo = () => {
return (
<div>
<ProForm
formType="pure"
formDatas={ [
{
label: 'input',
key: 'input',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"24",
},
]}
/>
</div>
);
}
export default Demo
```
## 布局
### 基本布局
> 通过span(继承于uiw/Graid/Col)
```jsx mdx:preview
import ReactDOM from 'react-dom';
import React from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
const Demo = () => {
return (
<div>
<ProForm
formType="pure"
formDatas={ [
{
label: 'input',
key: 'input',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"24",
},
{
label: 'input',
key: 'input2',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"12",
},
{
label: 'input',
key: 'input3',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"12",
},
{
label: 'input',
key: 'input4',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"8",
},
{
label: 'input',
key: 'input5',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"8",
},
{
label: 'input',
key: 'input6',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"8",
},
]}
/>
</div>
);
}
export default Demo
```
### 基本布局 横排
```jsx mdx:preview
import ReactDOM from 'react-dom';
import React from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
const Demo = () => {
return (
<div>
<ProForm
formType="pure"
formType="card"
layout="horizontal"
formDatas={[
{
label: 'input',
key: 'input',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"24",
},
{
label: 'input',
key: 'input2',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"12",
},
{
label: 'input',
key: 'input3',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"12",
},
{
label: 'input',
key: 'input4',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"8",
},
{
label: 'input',
key: 'input5',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"8",
},
{
label: 'input',
key: 'input6',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"8",
},
]}
/>
</div>
);
}
export default Demo
```
### 只读布局
> 通过readSpan(继承于uiw/Descriptions.Item)
```jsx mdx:preview
import React from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
const Demo = () => {
return (
<div>
<ProForm
readOnly={true}
formType="pure"
className="bbb"
formDatas={ [
{
label: 'input',
key: 'input',
widget: 'input',
initialValue: '',
widgetProps: {},
readSpan:3,
},
{
label: 'input',
key: 'input2',
widget: 'input',
initialValue: '',
widgetProps: {},
readSpan:3,
},
{
label: 'input',
key: 'input3',
widget: 'input',
initialValue: '',
widgetProps: {},
readSpan:3,
},
{
label: 'input',
key: 'input4',
widget: 'input',
initialValue: '',
widgetProps: {},
readSpan:3,
},
{
label: 'input',
key: 'input5',
widget: 'input',
initialValue: '',
widgetProps: {},
readSpan:2
},
{
label: 'input',
key: 'input6',
widget: 'input',
initialValue: '',
widgetProps: {},
readSpan:1,
},
]}
/>
</div>
);
}
export default Demo
```
## 基本使用
> 与uiw/form使用保持一致
```jsx mdx:preview
import ReactDOM from 'react-dom';
import React, { useState } from 'react';
import { ProForm } from '@uiw-admin/components'
import { Button,Notify,Slider } from 'uiw'
const Demo = () => {
const [state,setState] = React.useState({})
const [option] = React.useState([
{ value: 1, label: '苹果' },
{ value: 2, label: '西瓜' },
{ value: 3, label: '香蕉' },
{ value: 4, label: '东北大冻梨' },
{ value: 5, label: '香蕉' },
{ value: 6, label: '葡萄' },
{ value: 6, label: '哈密瓜' },
])
const [loading, setLoading] = React.useState(false)
// 模拟搜索
const handleSearch = ( type = '' , name = '' ) => {
if (type === 'searchSelect') {
setLoading(true)
setTimeout(() => {
setLoading(false)
}, 2000)
}
}
return (
<>
<ProForm
// 表单类型
formType="collapse"
title="基本使用(与uiw/form使用保持一致)"
// 自定义组件
customWidgetsList={{
slider: Slider,
}}
// 是否展示uiw/form提交按钮
showSaveButton
// 是否展示uiw/form重置按钮
showResetButton
// 提交后验证
onSubmit={(initial, current) => {
const errorObj = {};
if (!current?.input) {
errorObj.input = 'input不能为空';
}
if (Object.keys(errorObj).length > 0) {
const err = new Error();
err.filed = errorObj;
Notify.error({ title: '提交失败!' });
throw err;
}
setState(current)
// 调用请求接口
}}
formDatas={[
{
label: 'input',
key: 'input',
widget: 'input',
initialValue: '',
widgetProps: {},
help:"input不能为空",
rules: [
{ required:true, message: 'input不能为空' }
]
},
{
label: 'textarea',
key: 'textarea',
widget: 'textarea',
span:24,
colstyle:{ maxWidth:800 }
},
{
label: 'select',
key: 'select',
widget: 'select',
option: [
{ value: 1, label: '苹果' },
{ value: 2, label: '西瓜' },
{ value: 3, label: '香蕉' },
{ value: 4, label: '东北大冻梨' }
],
},
{
label: 'switch',
key: 'switch',
widget: 'switch',
},
{
label: 'radio',
widget: 'radio',
key: 'radio',
option: [
{ label: '男', value: 'man' },
{ label: '女', value: 'girl' }
],
},
{
label: '多选框',
widget: 'checkbox',
key: 'checkbox',
option: [
{ label: '四川菜', value: 'sichuan' },
{ label: '湖北菜', value: 'hubei' }
],
},
{
label: '年月日时分秒',
key: 'dateInputsecond',
widget: 'dateInput',
widgetProps: {
format: 'YYYY-MM-DD HH:mm:ss'
},
},
{
label: '年月日',
key: 'dateInput',
widget: 'dateInput',
widgetProps: {
format: 'YYYY-MM-DD'
},
},
{
label: '年月',
key: 'monthPicker',
widget: 'monthPicker',
widgetProps: {
format: 'YYYY-MM'
},
},
{
label: '时分秒',
key: 'timePicker',
widget: 'timePicker',
},
{
label: 'searchSelect',
key: 'searchSelect',
widget: 'searchSelect',
option: option,
widgetProps: {
mode:"multiple",
onSearch: handleSearch.bind(this,'searchSelect'),
onChange: (value) => console.log('changevalue', value),
onSelect: (value) => console.log('selectvalue', value),
loading: loading,
allowClear: true,
showSearch: true,
style:{ width:"100%" }
},
},
{
label: '评分',
key: 'rate',
widget: 'rate',
},
// 只读模式下支持读取React.ReactNode
{
label: '自定义组件',
key: 'slider',
widget: 'slider',
readSpan: 2,
span:"24"
},
{
label: '上传组件',
key: 'upload',
widget: 'upload',
span: '24',
readSpan: 3,
widgetProps: {
uploadType: 'card',
multiple: true,
maxNumber: 2,
showFileIcon: {
showPreviewIcon: true,
showRemoveIcon: true,
},
},
},
{
label: 'searchTree',
key: 'searchTree',
widget: 'searchTree',
span: '24',
readSpan: 3,
widgetProps:{
allowClear:true,
onSearch:(searchValue)=>console.log('SearchTree-> SearchTreeOption',searchValue),
onChange:(selectedAll, selectd, isChecked)=>console.log('SearchTree-> onChange',selectedAll, selectd, isChecked)
},
initialValue:[],
option:[
{
label: '上海市',
key: '1-0-0',
children:[
{ label: '黄浦区', key: '1-0-1' },
{ label: '卢湾区', key: '1-0-2' },
{
label: '徐汇区',
key: '1-0-3',
children:[
{ label: '半淞园路街道', key: '1-1-0' },
{ label: '南京东路街道', key: '1-2-0' },
{ label: '外滩街道', key: '1-3-0' },
]
},
]
}
]
}
]}
/>
<div style={{ maxWidth: 200 }}>
<pre style={{ padding: '10px 0 0 10px' }}>{JSON.stringify(state, null, 2)}</pre>
</div>
</>
)
}
export default Demo
```
## 通过useForm
> (提交,重置,设置)
> - 我们可以通过useForm注册form表单实例进行验证;重置;设置。(submitvalidate;getError;getFieldValues;setFields;resetForm...)
> - 我们也可以通过传递rules配置验证规则(支持正则,required,回调验证)
```jsx mdx:preview
import React from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
import { Button } from 'uiw'
const Demo = () => {
const [state,setState] = React.useState({
input:'',
upload: []
})
const form = useForm()
return (
<div>
<ProForm
form={form}
title="通过form api进行表单提交"
formType="card"
formDatas={[
{
label: 'input',
key: 'input',
widget: 'input',
initialValue: state.input,
widgetProps: {},
span:"24",
rules: [
{ required:true, message: 'input不能为空' },
{ pattern: new RegExp(/[1][3][0-9]{9}$/), message: "请输入正确手机号" },
]
},
{
label: 'upload',
key: 'upload',
widget: 'upload',
initialValue: state.upload,
widgetProps:{
uploadType: 'card',
},
},
]}
/>
<Button
style={{ marginTop:10,width:80 }}
type="primary"
onClick={async () => {
// 触发验证
await form.submitvalidate();
// 获取错误信息
const errors = form.getError();
if(errors && Object.keys(errors).length > 0 ) return;
const value = form.getFieldValues?.();
setState(value);
// 调用请求接口
}}
>
保存
</Button>
<Button
style={{ marginTop:10,width:80 }}
type="primary"
onClick={()=>{
form.resetForm()
setState({})
}}
>
重置
</Button>
<Button
style={{ marginTop:10,width:80 }}
type="primary"
onClick={()=> {
form.setFields({
input:'1234',
upload:[ { dataURL: 'https://avatars2.githubusercontent.com/u/1680273?s=40&v=4', name: 'uiw.png' }]
})
setState({
input:'1234',
upload:[ { dataURL: 'https://avatars2.githubusercontent.com/u/1680273?s=40&v=4', name: 'uiw.png' }]
})
} }
>
设置
</Button>
<div style={{ maxWidth: 500 }}>
<pre style={{ padding: '10px 0 0 10px' }}>{JSON.stringify(state, null, 2)}</pre>
</div>
</div>
);
}
export default Demo
```
## 多个表单
### 基础提交
```jsx mdx:preview
import React from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
import { Button } from 'uiw'
const Demo = () => {
const [state,setState] = React.useState({})
const form = useForm()
const form2 = useForm()
return (
<div>
<ProForm
form={form}
title="表单一"
formType="card"
formDatas={ [
{
label: 'input',
key: 'input',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"24",
rules: [
{ required: true, message: '请输入' },
{ pattern: new RegExp(/[1][3][0-9]{9}$/), message: "请输入正确手机号" },
]
},
]}
/>
<div style={{ marginTop:15 }} />
<ProForm
formType="pure"
form={form2}
title="表单二"
formType="card"
formDatas={ [
{
label: 'input2',
key: 'input2',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"24",
rules: [
{
validator: (value = '') => {
if(!value) return false
return true
},
message: "请输入"
},
]
},
{
label: 'input3',
key: 'input3',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"24",
rules: [
{
validator: (value = '') => {
if(!value) return "请输入"
return true
},
},
]
},
]}
/>
<Button
style={{ marginTop:10,width:80 }}
type="primary"
onClick={ async ()=>{
// 触发验证
await form?.submitvalidate()
await form2?.submitvalidate()
// 获取错误信息
const errors = form.getError()
const errors2 = form2.getError()
if(errors && Object.keys(errors).length > 0 ) return
if(errors2 && Object.keys(errors2).length > 0 ) return
// 获取表单值
const value = form.getFieldValues?.()
const value2 = form2.getFieldValues?.()
const params = {...value,...value2}
setState(params)
// 调用请求接口
}}>
保存
</Button>
<div style={{ maxWidth: 500 }}>
<pre style={{ padding: '10px 0 0 10px' }}>{JSON.stringify(state, null, 2)}</pre>
</div>
</div>
);
}
export default Demo
```
### promise提交
> (通过validateFieldsAndGetValue方法先验证后获取值)
```jsx mdx:preview
import React from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
import { Button } from 'uiw'
const Demo = () => {
const [state,setState] = React.useState({})
const form = useForm()
const form2 = useForm()
const asyncAwaitFormList = (arr=[]) => {
return (
arr && arr.length>0 && Promise.all(arr).then((vals) =>{
return vals
})
)
};
return (
<div>
<ProForm
form={form}
title="表单一"
formType="card"
formDatas={ [
{
label: 'input',
key: 'input',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"24",
rules: [
{ required: true, message: '请输入' },
{ pattern: new RegExp(/[1][3][0-9]{9}$/), message: "请输入正确手机号" },
]
},
]}
/>
<div style={{ marginTop:15 }} />
<ProForm
formType="pure"
form={form2}
title="表单二"
formType="card"
formDatas={ [
{
label: 'input2',
key: 'input2',
widget: 'input',
initialValue: '',
widgetProps: {},
span:"24",
rules: [
{
validator: (value = '') => {
if(!value) return false
return true
},
message: "请输入"
},
]
},
]}
/>
<Button
style={{ marginTop:10,width:80 }}
type="primary"
onClick={ async ()=>{
// 触发验证获取值
const values = await asyncAwaitFormList([form?.validateFieldsAndGetValue(),form2?.validateFieldsAndGetValue()])
let obj = {};
values.forEach((item) => Object.assign(obj, item));
setState(obj)
// 调用请求接口
}}>
保存
</Button>
<div style={{ maxWidth: 500 }}>
<pre style={{ padding: '10px 0 0 10px' }}>{JSON.stringify(state, null, 2)}</pre>
</div>
</div>
);
}
export default Demo
```
## 动态添加表单
### uiw/form提交
```jsx mdx:preview
import React, { useState,useRef } from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
import { Button,Card } from 'uiw'
const Demo = () => {
const form = useForm()
const formRefList = useRef([])
const [state,setState] = useState([])
const [items,setItems] = useState([])
const [option,setOption] = React.useState([])
const [loading, setLoading] = React.useState(false)
// 过滤删除为null的ref
const formList = formRefList?.current.filter(n => n) || []
const asyncAwaitFormList = (arr=[]) => {
return (
arr && arr.length>0 && Promise.all(arr).then((vals) =>{
return vals
})
)
};
const addItems = (attr)=>[
{
label: '司机手机号',
key: 'phone',
widget: 'input',
initialValue: '',
required:true,
rules: [
{ required: true, message: '请输入' },
]
},
{
label: 'searchSelect',
key: 'searchSelect',
widget: 'searchSelect',
option: attr.searchSelect.option,
widgetProps: {
mode:"multiple",
onSearch: attr.searchSelect.onSearch,
loading: attr.searchSelect.loading,
allowClear: true,
showSearch: true,
style:{ width:"100%" }
},
},
]
const handleAddFormItems = (type,idx)=>{
if(type==='add'){
items.push(addItems)
}
if(type==='delete'){
items.splice(idx,1)
}
setItems([...items])
}
// 模拟搜索
const handleSearch = ( type = '' , name = '' ) => {
if (type === 'searchSelect') {
setLoading(true)
setOption([
{ value: 1, label: '苹果' },
{ value: 2, label: '西瓜' },
{ value: 3, label: '香蕉' },
{ value: 4, label: '东北大冻梨' },
])
setTimeout(() => {
setLoading(false)
}, 2000)
}
}
const handleSave = async ()=>{
const validateList = await formList.map(itm => itm.validateFieldsAndGetValue()) || []
const values = await asyncAwaitFormList(validateList)
setState(values)
// 调用接口
}
return (
<div>
{items.map((item, idx) => {
return (
<Card
title={`表单${idx + 1}`}
key={idx}
style={{ marginBottom:10 }}
extra={<span onClick={handleAddFormItems.bind(this,'delete',idx)}>删除</span>}
>
<ProForm
ref={(e) =>(formRefList.current[idx] = e)}
// 表单类型
formType="pure"
form={form}
cardProps={{
noHover: true,
}}
// 更新表单的值
buttonsContainer={{ justifyContent: 'flex-start' }}
formDatas={item({
searchSelect:{
option:option,
onSearch: handleSearch.bind(this,'searchSelect'),
loading:loading
}
})}
/>
</Card>
)
})}
<Button
style={{ marginTop:10,width:80 }}
type="primary"
onClick={handleAddFormItems.bind(this,'add')}>
新增
</Button>
<Button
style={{ marginTop:10,width:80 }}
type="primary"
onClick={() => handleSave()}>
保存
</Button>
<div style={{ maxWidth: 500 }}>
<pre style={{ padding: '10px 0 0 10px' }}>{JSON.stringify(state, null, 2)}</pre>
</div>
</div>
);
}
export default Demo
```
### promise提交
```jsx mdx:preview
import ReactDOM from 'react-dom';
import React, { useState,useRef } from 'react';
import { ProForm,useForm } from '@uiw-admin/components'
import { Button,Card } from 'uiw'
const Demo = () => {
const form = useForm()
const formRefList = useRef([])
const [state,setState] = useState([])
const [items,setItems] = useState([])
const [option,setOption] = React.useState([])
const [loading, setLoading] = React.useState(false)
// 过滤删除为null的ref
const formList = formRefList?.current.filter(n => n) || []
const asyncAwaitFormList = (arr=[]) => {
return (
arr && arr.length>0 && Promise.all(arr).then((vals) =>{
return vals
})
)
};
const addItems = (attr)=>[
{
label: '司机手机号',
key: 'phone',
widget: 'input',
initialValue: '',
rules: [
{ required: true, message: '请输入' },
]
},
{
label: 'searchSelect',
key: 'searchSelect',
widget: 'searchSelect',
option: attr.searchSelect.option,
widgetProps: {
mode:"multiple",
onSearch: attr.searchSelect.onSearch,
loading: attr.searchSelect.loading,
allowClear: true,
showSearch: true,
style:{ width:"100%" }
},
},
]
const handleAddFormItems = (type,idx)=>{
if(type==='add'){
items.push(addItems)
}
if(type==='delete'){
items.splice(idx,1)
}
setItems([...items])
}
// 模拟搜索
const handleSearch = ( type = '' , name = '' ) => {
if (type === 'searchSelect') {
setLoading(true)
setOption([
{ value: 1, label: '苹果' },
{ value: 2, label: '西瓜' },
{ value: 3, label: '香蕉' },
{ value: 4, label: '东北大冻梨' },
])
setTimeout(() => {
setLoading(false)
}, 2000)
}
}
const handleSave = async ()=>{
const validateList = formList.map(itm=> itm.validateFieldsAndGetValue()) || []
const values = await asyncAwaitFormList(validateList)
setState(values)
// 调用接口
}
return (
<div>
{items.map((item, idx) => {
return (
<Card
title={`表单${idx + 1}`}
key={idx}
style={{ marginBottom:10 }}
extra={<span onClick={handleAddFormItems.bind(this,'delete',idx)}>删除</span>}
>
<ProForm
className="aaa"
ref={(e) =>(formRefList.current[idx] = e)}
// 表单类型
formType="pure"
form={form}
cardProps={{
noHover: true,
}}
// 更新表单的值
buttonsContainer={{ justifyContent: 'flex-start' }}
formDatas={item({
searchSelect:{
option:option,
onSearch: handleSearch.bind(this,'searchSelect'),
loading:loading
}
})}
/>
</Card>
)
})}
<Button
style={{ marginTop:10,width:80 }}
type="primary"
onClick={handleAddFormItems.bind(this,'add')}>
新增
</Button>
<Button
style={{ marginTop:10,width:80 }}
type="primary"
onClick={() => handleSave()}>
保存
</Button>
<div style={{ maxWidth: 500 }}>
<pre style={{ padding: '10px 0 0 10px' }}>{JSON.stringify(state, null, 2)}</pre>
</div>
</div>
);
}
export default Demo
```
## 只读模式
```jsx mdx:preview
import ReactDOM from 'react-dom';
import { ProForm,useForm } from '@uiw-admin/components'
import { formatter } from 'uiw'
import React, { useState } from 'react';
const Demo = () => {
const [ queryInfo ] = useState({
input:"Jason",
textarea:"Jason",
select:"Jason",
dateInputsecond: '2021-1-21 23:59:59',
dateInput: '2021-1-21',
monthPicker: '2021-1',
timePicker: '2021-1-21 22:59:59',
searchSelect:["Jason"],
rate:2
})
const form = useForm()
return (
<ProForm
form={form}
readOnly={true}
title="只读模式"
formType="pure"
layout="horizontal"
// 只读模式下调整 一行的 DescriptionItems 数量,其余参数参考uiw/Descriptions
readOnlyProps={{ column:2 }}
formDatas={
[
{
label: 'input',
key: 'input',
widget: 'input',
// 只读模式下支持读取React.ReactNode
initialValue: queryInfo?.input,
},
{
label: 'textarea',
key: 'textarea',
widget: 'textarea',
initialValue: queryInfo?.textarea,
},
{
label: 'select',
key: 'select',
widget: 'select',
option:[{label:"Jason",value:"Jason"}],
initialValue: queryInfo?.select,
},
{
label: 'dateInput',
key: 'dateInputsecond',
widget: 'dateInput',
widgetProps: {
// 年月日时分秒
format: 'YYYY-MM-DD HH:mm:ss'
},
initialValue: queryInfo?.dateInputsecond
},
{
label: 'dateInput',
key: 'dateInput',
widget: 'dateInput',
widgetProps: {
// 年月日
format: 'YYYY-MM-DD'
},
initialValue: queryInfo?.dateInput
},
{
label: 'monthPicker',
key: 'monthPicker',
widget: 'monthPicker',
widgetProps: {
// 年月
format: 'YYYY-MM'
},
initialValue: queryInfo?.monthPicker
},
{
label: 'timePicker',
key: 'timePicker',
widget: 'timePicker',
initialValue: queryInfo.timePicker && new Date(queryInfo.timePicker)
},
{
label: 'searchSelect',
key: 'searchSelect',
widget: 'searchSelect',
widgetProps:{
mode:"multiple",
},
option:[{label:"Jason",value:"Jason"}],
initialValue:queryInfo.searchSelect || []
},
{
label: 'rate',
key: 'rate',
widget: 'rate',
initialValue:queryInfo.rate
},
{
label: 'upload',
key: 'upload',
widget: 'upload',
widgetProps:{
uploadType: 'card',
},
initialValue: [
{
dataURL: 'https://avatars2.githubusercontent.com/u/1680273?s=40&v=4',
name: 'uiw.png',
},
]
},
]}
/>
);
}
export default Demo
```
## 自定义表单组件
> 给组件传`value`, `onChange` 一个是值 一个是组件更改数据回调
```jsx mdx:preview
import { ProForm,useForm } from '@uiw-admin/components'
import { formatter, Input, Button } from 'uiw'
import React, { useState } from 'react';
const Inputs = ({value, onChange}) => {
return (
<>
<Button style={{ marginRight: 10, width: 200 }}>按钮</Button>
<Input
placeholder="请输入内容"
value={value}
onChange={e => { onChange(e.target.value) }} />
</>
)
}
const Demo = () => {
const [ queryInfo ] = useState({
input:"Jason",
})
const form = useForm()
return (
<ProForm
customWidgetsList={{inputs: Inputs}}
form={form}
title="只读模式"
formType="pure"
formDatas={[
{
label: '自定义组件',
key: 'input',
widget: 'inputs',
// 只读模式下支持读取React.ReactNode
initialValue: queryInfo.input,
},
]}
/>
);
}
export default Demo
```
## Props
> 继承uiw-Form
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| title | 标题 | `string` | - |
| formType | 表单类型 | `collapse` `card` `pure` | `card` |
| layout | 表单布局 | `horizontal \| vertical` | `vertical` |
| form | useForm返回值,替换原有submitRef作用可进行表单验证 | `UseFormProps` | - |
| readOnly | `是否是只读模式模式` | `boolean` | false |
| readOnlyProps | 只读模式 参考Descriptions参数 | `DescriptionsProps` | `{}` |
| formDatas | 表单项集合 | `FormItemsProps[]` | `[]` |
| showSaveButton | 展示提交按钮 | `boolean` | `false` |
| showResetButton | 展示重置按钮 | `boolean` | `false` |
| saveButtonProps | 提交按钮api;继承于uiw/button | `ButtonProps` | - |
| resetButtonProps | 重置按钮api;继承于uiw/button | `ButtonProps` | - |
| buttonsContainer | buttons容器样式(可调整button布局) | `React.CSSProperties` | - |
| customWidgetsList | 可配置自定义组件 | `{ [key: string]: any }` | `{}` |
| cardProps | uiw`Card` API | `CardProps` | `{}` |
| collapseProps | uiw`Collapse` API | `CollapseProps` | `{}` |
| collapsePanelProps | uiw`Collapse.Panel` API | `CollapsePanelProps` | `{}` |
| colProps | uiw`Col` API,公共属性 | `colProps` | - |
| onSubmit | 提交表单回调 需配合btns,继承uiw/form submit | `(initial: Record<string, any>, current: Record<string, any>) => void` | - |
| onChange | 表单值变化回调,继承uiw/form onChange | `(initial: Record<string, any>, current: Record<string, any>) => void` | - |
| onSubmitError | 调用 onSubmit 抛出的任何错误。从字段名称返回对象映射。 继承uiw/form onSubmitError | `(error: any) => void` | - |
### saveButtonProps resetButtonProps
更多属性文档请参考 [uiw/button](https://uiwjs.github.io/#/components/button)
| 参数 | 说明 | 类型 | 默认值 |
| -------- | -------- | ------------------------ | ------ |
| label | 按钮标题 | string | 提交/重置 |
### FormItemsProps
> 继承uiw-FormItem
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| label | 表单项名称 | `string` | - |
| key| 表单项key | `string` | - |
| widget | 表单项类型 | `sring` | - |
| initialValue | 表单项值,可以是默认值 | `any \| any[]` | - |
| option | 数据化选项内容, widget为 radio、checkbox、select 生效 | `OptionsProps[]` | - |
| widgetProps | 表单组件其余参数,参考uiw表单组件 | `any` | - |
| hide | 是否显示 | `boolean` | true |
| span | 非只读模式下,可以通过指定 24 列中每列的宽度来创建基本网格系统 | `string` | `'8'` |
| readSpan | 只读模式下包含列的数量 参考Descriptions.Item | `number` | `1` |
| rules | 验证规则 | `RulesProps[]` | - |
| colstyle | Col(uiw/Grid)样式 | `React.CSSProperties` | - |
### RulesProps
| 参数 | 说明 | 类型 | 默认值 |
| -------- | -------- | ------------------------ | ------ |
| message | 验证提示消息 | `string` | - |
| pattern | 验证正则 | `RegExp` | - |
| validator | 自定义验证规则 | `(value: any \| any[]) => boolean\|string` | - |
| required | 是否必填 | `boolean` | - |
### OptionsProps
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| label | 必传。名称 | `string` | - |
| value | 必传。key | `string \| number` | - |
| disabled | 是否禁用 | `boolean` | - |
## useForm
### response
> - v5.2.14(~~clickRef~~)
> - v5.2.18(~~formStateList~~) (~~setFormStateList~~) (~~errorsRef~~)
| 参数 | 说明 | 类型 | 默认值 |
| -------- | -------- | ------------------------ | ------ |
| submitvalidate | 表单验证 | `()=>void` | - |
| resetForm | 重置表单值 | `()=>void` | - |
| onSubmit | 表单提交 | `(e: React.FormEvent)=>void` | - |
| getFieldValues | 获取表单值 | `()=>void` | - |
| getError | 获取表单错误 | `()=>void` | - |
| setFields | 设置表单的值 | `(fields: FormState['current'])=>void` | `[]` |
| validateFieldsAndGetValue | 验证并获取值 | `()=>Promise<any>` | `[]` |
## 注意
> [继承于uiw/Form,请参考uiw/From以及表单组件](https://uiwjs.github.io/#/components/form),
默认集成了`Input`, `InputNumber`, `Checkbox`, `Switch`, `Textarea`,`DateInput`, `TimePicker`,
`MonthPicker`, `SearchSelect`, `Select`, `Radio`, `selectMultiple`, `Rate`, `Upload`。
<!--rehype:style=border-left: 8px solid #ffe564;background-color: #ffe56440;padding: 12px 16px;-->
## 贡献者
感谢所有的贡献者,欢迎开发者为开源项目贡献力量。
<a href="https://github.com/uiwjs/uiw-admin/graphs/contributors">
<img src="https://uiwjs.github.io/uiw-admin/CONTRIBUTORS.svg" />
</a>
## License
Licensed under the MIT License.