-
Notifications
You must be signed in to change notification settings - Fork 328
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(form): fixed dynamic rendering of form default data (#3145)
* chore(form): fixed variable naming misspellings * chore(form): fixed type issues * fix(Form): fixed issue #3076 * test(form): add a test case for issue #3076 * fix(FormItem): fixed formItem default value * chore(Form): 调整 floatingFormData 逻辑 - 将 floatingFormDataRef 移至 formContext - 将 FormItem 渲染后删除对应游离值的逻辑移至 userFormItemInitialData hook 内 * docs(Form): 将 FQA 中的 【如何根据某个字段变化动态展示数据】 改为 【字段联动的表单示例】 * chore(Form): update test snapshots * chore: update snapshot * chore: update common --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
- Loading branch information
1 parent
778a2f7
commit 476dd87
Showing
13 changed files
with
367 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import React from 'react'; | ||
import Form from '../Form'; | ||
import Radio from '../../radio'; | ||
import Button from '../../button'; | ||
|
||
const { FormItem } = Form; | ||
|
||
export default function FormExample() { | ||
const [form] = Form.useForm(); | ||
const setMessage = () => { | ||
form.setFieldsValue({ | ||
type: 'cold', | ||
ice: '1', | ||
}); | ||
}; | ||
|
||
return ( | ||
<Form form={form} colon labelWidth={100}> | ||
<FormItem label="类型" name="type" initialData="hot"> | ||
<Radio.Group> | ||
<Radio value="hot">热饮</Radio> | ||
<Radio value="cold">冷饮</Radio> | ||
</Radio.Group> | ||
</FormItem> | ||
<FormItem shouldUpdate={(prev, next) => prev.type !== next.type}> | ||
{({ getFieldValue }) => { | ||
if (getFieldValue('type') === 'cold') { | ||
return ( | ||
<FormItem label="冰量" key="ice" name="ice"> | ||
<Radio.Group> | ||
<Radio value="0">正常冰</Radio> | ||
<Radio value="1">少冰</Radio> | ||
<Radio value="2">去冰</Radio> | ||
</Radio.Group> | ||
</FormItem> | ||
); | ||
} | ||
return null; | ||
}} | ||
</FormItem> | ||
|
||
<FormItem style={{ marginLeft: 100 }}> | ||
<Button onClick={setMessage}>选择冷饮-少冰</Button> | ||
</FormItem> | ||
</Form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import React, { useEffect } from 'react'; | ||
import get from 'lodash/get'; | ||
import unset from 'lodash/unset'; | ||
import isEmpty from 'lodash/isEmpty'; | ||
|
||
// 兼容特殊数据结构和受控 key | ||
import Tree from '../../tree/Tree'; | ||
import Upload from '../../upload/upload'; | ||
import CheckTag from '../../tag/CheckTag'; | ||
import Checkbox from '../../checkbox/Checkbox'; | ||
import TagInput from '../../tag-input/TagInput'; | ||
import RangeInput from '../../range-input/RangeInput'; | ||
import Transfer from '../../transfer/Transfer'; | ||
import CheckboxGroup from '../../checkbox/CheckboxGroup'; | ||
import DateRangePicker from '../../date-picker/DateRangePicker'; | ||
import TimeRangePicker from '../../time-picker/TimeRangePicker'; | ||
|
||
import { useFormContext, useFormListContext } from '../FormContext'; | ||
import { FormItemProps } from '../FormItem'; | ||
|
||
// FormItem 子组件受控 key | ||
export const ctrlKeyMap = new Map(); | ||
ctrlKeyMap.set(Checkbox, 'checked'); | ||
ctrlKeyMap.set(CheckTag, 'checked'); | ||
ctrlKeyMap.set(Upload, 'files'); | ||
|
||
// FormItem 默认数据类型 | ||
export const initialDataMap = new Map(); | ||
[Tree, Upload, Transfer, TagInput, RangeInput, CheckboxGroup, DateRangePicker, TimeRangePicker].forEach((component) => { | ||
initialDataMap.set(component, []); | ||
}); | ||
[Checkbox].forEach((component) => { | ||
initialDataMap.set(component, false); | ||
}); | ||
|
||
export default function useFormItemInitialData(name: FormItemProps['name']) { | ||
let hadReadFloatingFormData = false; | ||
|
||
const { floatingFormDataRef, initialData: formContextInitialData } = useFormContext(); | ||
|
||
const { name: formListName, initialData: formListInitialData } = useFormListContext(); | ||
|
||
// 组件渲染后删除对应游离值 | ||
useEffect(() => { | ||
if (hadReadFloatingFormData) { | ||
const nameList = formListName ? [formListName, name].flat() : name; | ||
unset(floatingFormDataRef.current, nameList); | ||
} | ||
}, [hadReadFloatingFormData, floatingFormDataRef, formListName, name]); | ||
|
||
// 整理初始值 优先级:Form.initialData < FormList.initialData < FormItem.initialData < floatFormData | ||
function getDefaultInitialData({ | ||
children, | ||
initialData, | ||
}: { | ||
children: FormItemProps['children']; | ||
initialData: FormItemProps['initialData']; | ||
}) { | ||
if (name && !isEmpty(floatingFormDataRef.current)) { | ||
const nameList = formListName ? [formListName, name].flat() : name; | ||
const defaultInitialData = get(floatingFormDataRef.current, nameList); | ||
if (typeof defaultInitialData !== 'undefined') { | ||
hadReadFloatingFormData = true; | ||
return defaultInitialData; | ||
} | ||
} | ||
|
||
if (typeof initialData !== 'undefined') { | ||
return initialData; | ||
} | ||
|
||
if (name && formListInitialData.length) { | ||
const defaultInitialData = get(formListInitialData, name); | ||
if (typeof defaultInitialData !== 'undefined') return defaultInitialData; | ||
} | ||
|
||
if (name && formContextInitialData) { | ||
const defaultInitialData = get(formContextInitialData, name); | ||
if (typeof defaultInitialData !== 'undefined') return defaultInitialData; | ||
} | ||
|
||
if (typeof children !== 'function') { | ||
const childList = React.Children.toArray(children); | ||
const lastChild = childList[childList.length - 1]; | ||
if (lastChild && React.isValidElement(lastChild)) { | ||
// @ts-ignore | ||
const isMultiple = lastChild?.props?.multiple; | ||
return isMultiple ? [] : initialDataMap.get(lastChild.type); | ||
} | ||
} | ||
} | ||
|
||
return { | ||
getDefaultInitialData, | ||
}; | ||
} |
Oops, something went wrong.