未验证 提交 2bca895f 编写于 作者: J junjun666 提交者: GitHub

feat: 新增表单组件Form.useForm()创建form控制实例的功能 (#679)

上级 6d7cb69e
......@@ -19,6 +19,7 @@ interface T {
title2: string
title3: string
title4: string
title5: string
name: string
nameTip: string
nameTip1: string
......@@ -62,7 +63,8 @@ const FormDemo = () => {
title10: '顶部对齐',
title2: '表单校验',
title3: '带有初始值表单校验',
title4: '表单类型',
title4: 'Form.useForm 对表单数据域进行交互。',
title5: '表单类型',
name: '姓名',
nameTip: '请输入姓名',
nameTip1: '请输入姓名',
......@@ -103,7 +105,8 @@ const FormDemo = () => {
title10: 'Top Align',
title2: 'Validate Form',
title3: 'InitialValue Validate Type',
title4: 'Form Type',
title4: 'Interact with form data fields via Form.useForm',
title5: 'Form Type',
name: 'Name',
nameTip: 'Please enter your name',
nameTip1: 'Please enter name',
......@@ -177,6 +180,23 @@ const FormDemo = () => {
console.log('succeed', obj)
}
const [form] = Form.useForm()
const onMenuChange = (value: string | number | boolean) => {
switch (value) {
case 'male':
form.setFieldsValue({ note: 'Hi, man!' })
break
case 'female':
form.setFieldsValue({ note: 'Hi, lady!' })
break
case 'other':
form.setFieldsValue({ note: 'Hi there!' })
break
default:
}
}
return (
<>
<div className="demo">
......@@ -279,6 +299,33 @@ const FormDemo = () => {
</Cell>
</Form>
<h2>{translated.title4}</h2>
<Form
form={form}
onFinish={(obj) => submitSucceed(obj)}
onFinishFailed={(error) => submitFailed(error)}
>
<Form.Item
label={translated.name}
name="username"
rules={[{ required: true, message: translated.nameTip }]}
>
<Input placeholder={translated.nameTip1} type="text" />
</Form.Item>
<Form.Item label="标注" name="note">
<Input placeholder="请输入标注" type="string" />
</Form.Item>
<Form.Item label={translated.radiogroup} name="radiogroup">
<Radio.RadioGroup onChange={onMenuChange}>
<Radio value="male">male</Radio>
<Radio value="female">female</Radio>
<Radio value="other">other</Radio>
</Radio.RadioGroup>
</Form.Item>
<Cell>
<input type="submit" value={translated.submit} />
</Cell>
</Form>
<h2>{translated.title5}</h2>
<Form
onFinish={(obj) => submitSucceed(obj)}
onFinishFailed={(error) => submitFailed(error)}
......
......@@ -139,6 +139,57 @@ export default App;
```
:::
### Interact with form data fields via Form.useForm
:::demo
```tsx
import React from "react";
import { Form, Input, Cell } from '@nutui/nutui-react';
const App = () => {
const [form] = Form.useForm()
const onMenuChange = (value: string | number | boolean) => {
switch (value) {
case 'male':
form.setFieldsValue({ note: 'Hi, man!' })
break
case 'female':
form.setFieldsValue({ note: 'Hi, lady!' })
break
case 'other':
form.setFieldsValue({ note: 'Hi there!' })
break
default:
}
}
return (
<>
<Form
form={form}
onFinish={(obj) => submitSucceed(obj)}
onFinishFailed={(error) => submitFailed(error)}
>
<Form.Item label="Note" name="note">
<Input placeholder="please input note" type="string" />
</Form.Item>
<Form.Item label={translated.radiogroup} name="radiogroup">
<Radio.RadioGroup onChange={onMenuChange}>
<Radio value="male">male</Radio>
<Radio value="female">female</Radio>
<Radio value="other">other</Radio>
</Radio.RadioGroup>
</Form.Item>
<Cell>
<input type="submit" value={translated.submit} />
</Cell>
</Form>
</>
)
}
export default App;
```
:::
### Form Type
:::demo
......@@ -194,6 +245,7 @@ export default App;
| Attribute | Description | TYPE | DEFAULT |
|-------------|--------------------------|--------|--------|
| form`v1.4.8` | The form control instance created by Form.useForm() will be created automatically if not provided | FormInstance | |
| labelPosition | label's position,the default value is Right,can be Top、Left、Right | string | |
| starPositon | the position of the red asterisk next to the label of the required filed ,the default is Left,can be Left、Right | string | |
......@@ -225,8 +277,12 @@ Use the `rules` attribute of Form.Item to define verification rules. The optiona
### Form Instance Methods
Form.useForm() creates a Form instance, which is used to manage all data states.
| Name | Description | Attribute | Callback |
|-------------------|-----------------------------|-----|---------|
| getFieldValue | Get the value of the corresponding field name | - | (name: NamePath) => any |
| setFieldsValue | Set the value of the form | - | (values) => void |
| submit | the function of submit the form | - | Promise |
......
......@@ -149,6 +149,65 @@ export default App;
```
:::
### 通过 Form.useForm 对表单数据域进行交互。
:::demo
```tsx
import React from "react";
import { Form, Input, Cell } from '@nutui/nutui-react';
const App = () => {
const [form] = Form.useForm()
const onMenuChange = (value: string | number | boolean) => {
switch (value) {
case 'male':
form.setFieldsValue({ note: 'Hi, man!' })
break
case 'female':
form.setFieldsValue({ note: 'Hi, lady!' })
break
case 'other':
form.setFieldsValue({ note: 'Hi there!' })
break
default:
}
}
return (
<>
<Form
form={form}
onFinish={(obj) => submitSucceed(obj)}
onFinishFailed={(error) => submitFailed(error)}
>
<Form.Item
label={translated.name}
name="username"
rules={[{ required: true, message: translated.nameTip }]}
>
<Input placeholder={translated.nameTip1} type="text" />
</Form.Item>
<Form.Item label="标注" name="note">
<Input placeholder="请输入标注" type="string" />
</Form.Item>
<Form.Item label={translated.radiogroup} name="radiogroup">
<Radio.RadioGroup onChange={onMenuChange}>
<Radio value="male">male</Radio>
<Radio value="female">female</Radio>
<Radio value="other">other</Radio>
</Radio.RadioGroup>
</Form.Item>
<Cell>
<input type="submit" value={translated.submit} />
</Cell>
</Form>
</>
)
}
export default App;
```
:::
### 表单类型
......@@ -205,6 +264,7 @@ export default App;
| 参数 | 说明 | 类型 | 默认值 |
|-------------|--------------------------------------|--------|--------|
| form`v1.4.8` | 经 Form.useForm() 创建的 form 控制实例,不提供时会自动创建 | FormInstance | |
| labelPosition | 表单项 label 的位置,默认 Right,可设置为 Top、Left、Right | string | |
| starPositon | 必填表单项 label 的红色星标位置,默认 Left,可设置为 Left、Right | string | |
......@@ -236,8 +296,12 @@ export default App;
### Form 实例 Methods
Form.useForm()创建 Form 实例,用于管理所有数据状态。
| 方法名 | 说明 | 参数 | 返回值 |
|-------------------|-----------------------------|-----|---------|
| getFieldValue | 获取对应字段名的值 | - | (name: NamePath) => any |
| setFieldsValue | 设置表单的值 | - | (values) => void |
| submit | 提交表单进行校验的方法 | - | Promise |
......
......@@ -28,20 +28,28 @@ const PositionInfo: any = {
export const Form: FunctionComponent<
Partial<FormProps> & React.HTMLAttributes<HTMLFormElement>
> & { Item: typeof FormItem } = (props) => {
> & { Item: typeof FormItem } & { useForm: typeof useForm } = (props) => {
const {
children,
onFinish,
onFinishFailed,
labelPosition,
starPositon,
form,
...rest
} = {
...defaultProps,
...props,
}
const [formInstance] = useForm()
let formInstance: any = {}
if (Object.keys(form).length !== 0) {
formInstance = form
} else {
;[formInstance] = useForm()
}
formInstance.starPositon = starPositon
const { setCallback, submit } = formInstance
......@@ -72,3 +80,4 @@ export const Form: FunctionComponent<
Form.defaultProps = defaultProps
Form.displayName = 'NutForm'
Form.Item = FormItem
Form.useForm = useForm
......@@ -46,14 +46,15 @@ class FormStore {
...this.store,
...newStore,
}
// this.fieldEntities.forEach((enetity: FieldEntity) => {
// const { name } = enetity.props
// Object.keys(newStore).forEach((key) => {
// if (key === name) {
// enetity.onStoreChange()
// }
// })
// })
this.fieldEntities.forEach((enetity: FieldEntity) => {
const { name } = enetity.props
Object.keys(newStore).forEach((key) => {
if (key === name) {
enetity.onStoreChange()
}
})
})
}
/**
......@@ -93,7 +94,7 @@ class FormStore {
this.errList.push(...errors)
// 表单项更新
}
// entity.onStoreChange()
entity.onStoreChange()
})
})
return err
......
......@@ -45,6 +45,8 @@ export class FormItem extends React.Component<FieldProps> {
private cancelRegister: any
private isInitialValue: boolean = false
componentDidMount() {
// 注册组件实例到FormStore
this.cancelRegister = this.context.registerField(this)
......@@ -64,12 +66,13 @@ export class FormItem extends React.Component<FieldProps> {
const defaultvalue =
this.props.initialValue || (children as any).props?.defaultValue
if (defaultvalue) {
if (defaultvalue && !this.isInitialValue) {
setFieldsValue({ [name]: defaultvalue })
this.isInitialValue = true
}
return {
value: getFieldValue(name),
defaultValue: getFieldValue(name),
onChange: (
event: React.ChangeEvent<HTMLInputElement> | number | string | string[]
) => {
......@@ -91,7 +94,7 @@ export class FormItem extends React.Component<FieldProps> {
}
onStoreChange = () => {
// this.forceUpdate()
this.forceUpdate()
}
renderLayout = (childNode: React.ReactNode) => {
......@@ -175,7 +178,7 @@ export class FormItem extends React.Component<FieldProps> {
}
const returnChildNode = React.cloneElement(
restCNode,
this.getControlled(c as React.ReactElement)
this.getControlled(restCNode as React.ReactElement)
)
return this.renderLayout(returnChildNode)
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册