diff --git a/package.json b/package.json
index a83962876f..93b2a31341 100644
--- a/package.json
+++ b/package.json
@@ -105,7 +105,8 @@
"classnames": "^2.5.1",
"lodash.isequal": "^4.5.0",
"lodash.kebabcase": "^4.1.1",
- "react-transition-group": "^4.4.5"
+ "react-transition-group": "^4.4.5",
+ "rc-util": "^5.32.2"
},
"devDependencies": {
"@babel/core": "^7.23.9",
diff --git a/src/packages/form/demo.taro.tsx b/src/packages/form/demo.taro.tsx
index 3881c4d845..a0a9d56ca1 100644
--- a/src/packages/form/demo.taro.tsx
+++ b/src/packages/form/demo.taro.tsx
@@ -9,6 +9,7 @@ import Demo4 from './demos/taro/demo4'
import Demo5 from './demos/taro/demo5'
import Demo6 from './demos/taro/demo6'
import Demo7 from './demos/taro/demo7'
+import Demo8 from './demos/taro/demo8'
const FormDemo = () => {
const [translated] = useTranslate({
@@ -19,6 +20,7 @@ const FormDemo = () => {
relatedDisplay: '关联展示',
title4: 'Form.useForm 对表单数据域进行交互。',
title5: '表单类型',
+ title6: 'Form.useWatch 对表单数据监听',
validateTrigger: '校验触发时机',
},
'en-US': {
@@ -28,6 +30,7 @@ const FormDemo = () => {
relatedDisplay: 'Related Display',
title4: 'Interact with form data fields via Form.useForm',
title5: 'Form Type',
+ title6: 'Watch field data change with Form.useWatch',
validateTrigger: 'Validate Trigger',
},
})
@@ -50,6 +53,8 @@ const FormDemo = () => {
{translated.title5}
+ {translated.title6}
+
>
)
diff --git a/src/packages/form/demo.tsx b/src/packages/form/demo.tsx
index effa42d77a..1e19b33530 100644
--- a/src/packages/form/demo.tsx
+++ b/src/packages/form/demo.tsx
@@ -7,6 +7,7 @@ import Demo4 from './demos/h5/demo4'
import Demo5 from './demos/h5/demo5'
import Demo6 from './demos/h5/demo6'
import Demo7 from './demos/h5/demo7'
+import Demo8 from './demos/h5/demo8'
const FormDemo = () => {
const [translated] = useTranslate({
@@ -17,6 +18,7 @@ const FormDemo = () => {
relatedDisplay: '关联展示',
title4: 'Form.useForm 对表单数据域进行交互。',
title5: '表单类型',
+ title6: 'Form.useWatch 对表单数据监听',
validateTrigger: '校验触发时机',
},
'en-US': {
@@ -26,6 +28,7 @@ const FormDemo = () => {
relatedDisplay: 'Related Display',
title4: 'Interact with form data fields via Form.useForm',
title5: 'Form Type',
+ title6: 'Watch field data change with Form.useWatch',
validateTrigger: 'Validate Trigger',
},
})
@@ -47,6 +50,8 @@ const FormDemo = () => {
{translated.title5}
+ {translated.title6}
+
>
)
diff --git a/src/packages/form/demos/h5/demo8.tsx b/src/packages/form/demos/h5/demo8.tsx
new file mode 100644
index 0000000000..904caf4af7
--- /dev/null
+++ b/src/packages/form/demos/h5/demo8.tsx
@@ -0,0 +1,100 @@
+import React from 'react'
+import { Cell, Form, Input, Picker, Radio, Toast } from '@nutui/nutui-react'
+import { ArrowRight } from '@nutui/icons-react'
+
+const Demo8 = () => {
+ const pickerOptions = [
+ { value: 4, text: 'BeiJing' },
+ { value: 1, text: 'NanJing' },
+ { value: 2, text: 'WuXi' },
+ { value: 8, text: 'DaQing' },
+ { value: 9, text: 'SuiHua' },
+ { value: 10, text: 'WeiFang' },
+ { value: 12, text: 'ShiJiaZhuang' },
+ ]
+ const submitFailed = (error: any) => {
+ Toast.show({ content: JSON.stringify(error), icon: 'fail' })
+ }
+
+ const submitSucceed = (values: any) => {
+ Toast.show({ content: JSON.stringify(values), icon: 'success' })
+ }
+
+ const [form] = Form.useForm()
+ const usernameWatch = Form.useWatch('username', form)
+
+ const noteWatch = Form.useWatch((values) => {
+ return values.picker
+ }, form)
+
+ const genderWatch = Form.useWatch((values) => {
+ return values.gender
+ }, form)
+
+ return (
+ <>
+
+
+
+ args[1]}
+ onClick={(event, ref: any) => {
+ ref.open()
+ }}
+ >
+
+ {(value: any) => {
+ return (
+ po.value === value[0])[0]
+ ?.text
+ : 'Please select'
+ }
+ extra={}
+ align="center"
+ />
+ )
+ }}
+ |
+
+
+
+ male
+ female
+
+
+
+
+ 字段A:{usernameWatch}
+ |
+
+ Picker:{noteWatch}
+ |
+
+ 字段B:{genderWatch}
+ |
+ >
+ )
+}
+
+export default Demo8
diff --git a/src/packages/form/demos/taro/demo8.tsx b/src/packages/form/demos/taro/demo8.tsx
new file mode 100644
index 0000000000..c974ddb86a
--- /dev/null
+++ b/src/packages/form/demos/taro/demo8.tsx
@@ -0,0 +1,101 @@
+import React from 'react'
+import Taro from '@tarojs/taro'
+import { Cell, Form, Input, Picker, Radio } from '@nutui/nutui-react-taro'
+import { ArrowRight } from '@nutui/icons-react-taro'
+
+const Demo8 = () => {
+ const pickerOptions = [
+ { value: 4, text: 'BeiJing' },
+ { value: 1, text: 'NanJing' },
+ { value: 2, text: 'WuXi' },
+ { value: 8, text: 'DaQing' },
+ { value: 9, text: 'SuiHua' },
+ { value: 10, text: 'WeiFang' },
+ { value: 12, text: 'ShiJiaZhuang' },
+ ]
+ const submitFailed = (error: any) => {
+ Taro.showToast({ title: JSON.stringify(error), icon: 'error' })
+ }
+
+ const submitSucceed = (values: any) => {
+ Taro.showToast({ title: JSON.stringify(values), icon: 'success' })
+ }
+
+ const [form] = Form.useForm()
+ const usernameWatch = Form.useWatch('username', form)
+
+ const noteWatch = Form.useWatch((values) => {
+ return values.picker
+ }, form)
+
+ const genderWatch = Form.useWatch((values) => {
+ return values.gender
+ }, form)
+
+ return (
+ <>
+
+
+
+ args[1]}
+ onClick={(event, ref: any) => {
+ ref.open()
+ }}
+ >
+
+ {(value: any) => {
+ return (
+ po.value === value[0])[0]
+ ?.text
+ : 'Please select'
+ }
+ extra={}
+ align="center"
+ />
+ )
+ }}
+ |
+
+
+
+ male
+ female
+
+
+
+
+ 字段A:{usernameWatch}
+ |
+
+ Picker:{noteWatch}
+ |
+
+ 字段B:{genderWatch}
+ |
+ >
+ )
+}
+
+export default Demo8
diff --git a/src/packages/form/doc.md b/src/packages/form/doc.md
index 2b176efff3..2c5e8eeb1e 100644
--- a/src/packages/form/doc.md
+++ b/src/packages/form/doc.md
@@ -66,6 +66,14 @@ import { Form } from '@nutui/nutui-react'
:::
+### Form.useWatch 对表单数据监听
+
+:::demo
+
+
+
+:::
+
## Form
### Props
@@ -120,8 +128,6 @@ import { Form } from '@nutui/nutui-react'
### FormInstance
-Form.useForm()创建 Form 实例,用于管理所有数据状态。
-
| 属性 | 说明 | 类型 |
| --- | --- | --- |
| getFieldValue | 获取对应字段名的值 | `(name: NamePath) => any` |
@@ -131,6 +137,13 @@ Form.useForm()创建 Form 实例,用于管理所有数据状态。
| resetFields | 重置表单提示状态 | `() => void` |
| submit | 提交表单进行校验的方法 | `Promise` |
+### Hook
+
+| 方法名 | 说明 | 类型 |
+| --- | --- | --- |
+| Form.useForm | 创建 Form 实例,用于管理所有数据状态。 | `() => FormInstance` |
+| Form.useWatch | 用于直接获取 form 中字段对应的值。 | `(name: NamePath \| (values: T) => any,options: FormInstance \| WatchOptions) => any` |
+
## 主题定制
### 样式变量
diff --git a/src/packages/form/index.taro.ts b/src/packages/form/index.taro.ts
index 093d5218c8..15bf2a00c0 100644
--- a/src/packages/form/index.taro.ts
+++ b/src/packages/form/index.taro.ts
@@ -3,6 +3,7 @@ import { Form, FormProps } from './form.taro'
import { FormItem } from '../formitem/formitem.taro'
import { FormInstance } from './types'
import { useForm } from '@/packages/form/useform.taro'
+import useWatch from './useWatch.taro'
export type {
FormItemRuleWithoutValidator,
@@ -17,11 +18,13 @@ type CompoundedComponent = React.ForwardRefExoticComponent<
> & {
Item: typeof FormItem
useForm: typeof useForm
+ useWatch: typeof useWatch
}
const InnerForm = Form as CompoundedComponent
InnerForm.Item = FormItem
InnerForm.useForm = useForm
+InnerForm.useWatch = useWatch
export default InnerForm
diff --git a/src/packages/form/index.ts b/src/packages/form/index.ts
index 6563f8a986..b52d45d263 100644
--- a/src/packages/form/index.ts
+++ b/src/packages/form/index.ts
@@ -3,6 +3,7 @@ import { Form, FormProps } from './form'
import { FormItem } from '../formitem/formitem'
import { FormInstance } from './types'
import { useForm } from '@/packages/form/useform'
+import useWatch from './useWatch'
export type {
FormItemRuleWithoutValidator,
@@ -17,11 +18,13 @@ type CompoundedComponent = React.ForwardRefExoticComponent<
> & {
Item: typeof FormItem
useForm: typeof useForm
+ useWatch: typeof useWatch
}
const InnerForm = Form as CompoundedComponent
InnerForm.Item = FormItem
InnerForm.useForm = useForm
+InnerForm.useWatch = useWatch
export default InnerForm
diff --git a/src/packages/form/types.ts b/src/packages/form/types.ts
index e0350f8809..af265b8cc6 100644
--- a/src/packages/form/types.ts
+++ b/src/packages/form/types.ts
@@ -8,6 +8,7 @@ export interface FormItemRuleWithoutValidator {
type StoreValue = any
export type NamePath = string | number
+export type InternalNamePath = (string | number)[]
export interface Callbacks {
onValuesChange?: (values: Values) => void
@@ -30,6 +31,15 @@ export interface FormInstance {
validateFields: (nameList?: NamePath[]) => Promise
}
+export type InternalFormInstance = FormInstance & { _init: boolean }
+
+export type WatchCallBack = (
+ allValues: Store,
+ namePathList: InternalNamePath[]
+) => void
+export interface WatchOptions