feat: 选项类的组件 autoFill 支持配置 initAutoFill 属性 Close: #9391 (#9547)

This commit is contained in:
liaoxuezhi 2024-01-31 16:09:30 +08:00 committed by GitHub
parent 5a49c43a3d
commit 41d3b12ed7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 251 additions and 10 deletions

View File

@ -1558,6 +1558,16 @@ order: 2
}
```
**初始不填充**
从 3.1.0 版本开始,表单初始化时,选项有值时也会执行「自动填充」逻辑,从版本 6.1.0 版本开始 可以通过 `initAutoFill` 配置成 `false` 来关闭。
`initAutoFill` 有三种值分别如下,默认为 `fillIfNotSet`
- `fillIfNotSet` 如果目标值不存在则填充,如果目标值存在则不填充。
- `true` 总是填充,如果目标值存在则覆盖。
- `false` 总是不填充,如果目标值存在则不填充。
## 控制选项高度
> 1.10.0 及以上版本

View File

@ -54,7 +54,7 @@ import isPlainObject from 'lodash/isPlainObject';
import {normalizeOptions} from '../utils/normalizeOptions';
import {optionValueCompare} from '../utils/optionValueCompare';
import type {Option} from '../types';
import {resolveEventData} from '../utils';
import {deleteVariable, resolveEventData} from '../utils';
export {Option};
@ -203,6 +203,12 @@ export interface FormOptionsControl extends FormBaseControl {
autoFill?: {
[propName: string]: string;
};
/**
* @default fillIfNotSet
*
*/
initAutoFill?: boolean | 'fillIfNotSet';
}
export interface OptionsBasicConfig extends FormItemBasicConfig {
@ -303,6 +309,7 @@ export function registerOptionsControl(config: OptionsConfig) {
placeholder: 'Select.placeholder',
resetValue: '',
deleteConfirmText: 'deleteConfirm',
initAutoFill: 'fillIfNotSet',
...Control.defaultProps
};
static propsList: any = (Control as any).propsList
@ -314,6 +321,7 @@ export function registerOptionsControl(config: OptionsConfig) {
input: any;
mounted = false;
initedFilled = false;
constructor(props: OptionsProps) {
super(props);
@ -356,16 +364,27 @@ export function registerOptionsControl(config: OptionsConfig) {
JSON.stringify(formItem.getSelectedOptions(formItem.tmpValue)),
() =>
this.mounted &&
this.initedFilled &&
this.syncAutoFill(formItem.getSelectedOptions(formItem.tmpValue))
)
);
if (
options &&
formItem.tmpValue &&
formItem.getSelectedOptions(formItem.tmpValue).length
) {
this.syncAutoFill(formItem.getSelectedOptions(formItem.tmpValue));
if (formInited || !addHook) {
this.initedFilled = true;
this.props.initAutoFill !== false &&
this.syncAutoFill(
formItem.getSelectedOptions(formItem.tmpValue),
this.props.initAutoFill === 'fillIfNotSet'
);
} else if (addHook) {
addHook(() => {
this.initedFilled = true;
this.props.initAutoFill !== false &&
this.syncAutoFill(
formItem.getSelectedOptions(formItem.tmpValue),
this.props.initAutoFill === 'fillIfNotSet'
);
}, 'init');
}
// 默认全选。这里会和默认值\回填值逻辑冲突所以如果有配置source则不执行默认全选
@ -530,7 +549,7 @@ export function registerOptionsControl(config: OptionsConfig) {
}
}
syncAutoFill(selectedOptions: Array<any>) {
syncAutoFill(selectedOptions: Array<any>, skipIfExits = false) {
const {autoFill, multiple, onBulkChange, data} = this.props;
const formItem = this.props.formItem as IFormItemStore;
// 参照录入|自动填充
@ -579,13 +598,21 @@ export function registerOptionsControl(config: OptionsConfig) {
Object.keys(autoFill).forEach(key => {
const keys = keyToPath(key);
let value = getVariable(toSync, key);
if (skipIfExits) {
const originValue = getVariable(data, key);
if (typeof originValue !== 'undefined') {
value = originValue;
}
}
setVariable(result, key, value);
// 如果左边的 key 是一个路径
// 这里不希望直接把原始对象都给覆盖没了
// 而是保留原始的对象,只修改指定的属性
if (keys.length > 1 && isPlainObject(tmpData[keys[0]])) {
const value = getVariable(toSync, key);
// 存在情况依次更新同一子路径的多个keyeg: a.b.c1 和 a.b.c2所以需要同步更新data
setVariable(tmpData, key, value);
result[keys[0]] = tmpData[keys[0]];

View File

@ -399,3 +399,206 @@ test('Form:options:autoFill:validation', async () => {
expect(screen.queryByText(validationMsg1)).not.toBeInTheDocument();
expect(screen.queryByText(validationMsg2)).not.toBeInTheDocument();
});
test('6. AutoFill initAutoFill fillIfNotSet', async () => {
const onSubmit = jest.fn();
const {debug, container, getByText, findByText} = render(
amisRender(
{
type: 'page',
body: [
{
type: 'form',
title: 'The form',
controls: [
{
type: 'hidden',
name: 'aId',
value: 123
},
{
type: 'hidden',
name: 'bId'
},
{
type: 'radios',
name: 'a',
autoFill: {
aValue: '${value}',
aLabel: '${label}',
aId: '${id}',
bId: '${id}'
},
value: 'a',
options: [
{
label: 'OptionA',
value: 'a',
id: 233
},
{
label: 'OptionB',
value: 'b'
}
]
}
],
submitText: 'Submit'
}
]
},
{
onSubmit: onSubmit
},
makeEnv()
)
);
await wait(200);
fireEvent.click(getByText(/Submit/));
await wait(200);
expect(onSubmit).toBeCalledTimes(1);
expect(onSubmit.mock.calls[0][0]).toMatchObject({
aId: 123,
a: 'a',
aValue: 'a',
aLabel: 'OptionA',
bId: 233
});
});
test('7. AutoFill initAutoFill false', async () => {
const onSubmit = jest.fn();
const {debug, container, getByText, findByText} = render(
amisRender(
{
type: 'page',
body: [
{
type: 'form',
title: 'The form',
controls: [
{
type: 'hidden',
name: 'aId',
value: 123
},
{
type: 'hidden',
name: 'bId'
},
{
type: 'radios',
name: 'a',
autoFill: {
aValue: '${value}',
aLabel: '${label}',
aId: '${id}',
bId: '${id}'
},
initAutoFill: false,
value: 'a',
options: [
{
label: 'OptionA',
value: 'a',
id: 233
},
{
label: 'OptionB',
value: 'b'
}
]
}
],
submitText: 'Submit'
}
]
},
{
onSubmit: onSubmit
},
makeEnv()
)
);
await wait(200);
fireEvent.click(getByText(/Submit/));
await wait(200);
expect(onSubmit).toBeCalledTimes(1);
expect(onSubmit.mock.calls[0][0]).toMatchObject({
aId: 123,
a: 'a'
});
});
test('8. AutoFill initAutoFill true', async () => {
const onSubmit = jest.fn();
const {debug, container, getByText, findByText} = render(
amisRender(
{
type: 'page',
body: [
{
type: 'form',
title: 'The form',
controls: [
{
type: 'hidden',
name: 'aId',
value: 123
},
{
type: 'hidden',
name: 'bId'
},
{
type: 'radios',
name: 'a',
autoFill: {
aValue: '${value}',
aLabel: '${label}',
aId: '${id}',
bId: '${id}'
},
initAutoFill: true,
value: 'a',
options: [
{
label: 'OptionA',
value: 'a',
id: 233
},
{
label: 'OptionB',
value: 'b'
}
]
}
],
submitText: 'Submit'
}
]
},
{
onSubmit: onSubmit
},
makeEnv()
)
);
await wait(200);
fireEvent.click(getByText(/Submit/));
await wait(200);
expect(onSubmit).toBeCalledTimes(1);
expect(onSubmit.mock.calls[0][0]).toMatchObject({
aId: 233,
a: 'a',
aValue: 'a',
aLabel: 'OptionA',
bId: 233
});
});

View File

@ -283,6 +283,7 @@ test('options:autoFill-merge', async () => {
makeEnv({})
)
);
await wait(200);
fireEvent.click(getByText('选项1'));
await wait(300);