Skip to content

Commit 5265440

Browse files
committed
feat: formate validateFields values #4964
1 parent c07e3f0 commit 5265440

File tree

4 files changed

+99
-13
lines changed

4 files changed

+99
-13
lines changed

components/form/Form.tsx

+8-13
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import classNames from '../_util/classNames';
55
import warning from '../_util/warning';
66
import type { FieldExpose } from './FormItem';
77
import FormItem from './FormItem';
8-
import { getNamePath, containsNamePath } from './utils/valueUtil';
8+
import { getNamePath, containsNamePath, cloneByNamePathList } from './utils/valueUtil';
99
import { defaultValidateMessages } from './utils/messages';
1010
import { allPromiseFinish } from './utils/asyncUtil';
1111
import { toArray } from './utils/typeUtil';
@@ -133,7 +133,6 @@ const Form = defineComponent({
133133
);
134134
const lastValidatePromise = ref();
135135
const fields: Record<string, FieldExpose> = {};
136-
137136
const addField = (eventKey: string, field: FieldExpose) => {
138137
fields[eventKey] = field;
139138
};
@@ -197,19 +196,15 @@ const Form = defineComponent({
197196
}
198197
};
199198
// eslint-disable-next-line no-unused-vars
200-
const getFieldsValue = (nameList: NamePath[] | true = true) => {
201-
const values: any = {};
202-
Object.values(fields).forEach(({ fieldName, fieldValue }) => {
203-
values[fieldName.value] = fieldValue.value;
204-
});
199+
const getFieldsValue = (nameList: InternalNamePath[] | true = true) => {
205200
if (nameList === true) {
206-
return values;
201+
const allNameList = [];
202+
Object.values(fields).forEach(({ namePath }) => {
203+
allNameList.push(namePath.value);
204+
});
205+
return cloneByNamePathList(props.model, allNameList);
207206
} else {
208-
const res: any = {};
209-
toArray(nameList as NamePath[]).forEach(
210-
namePath => (res[namePath as string] = values[namePath as string]),
211-
);
212-
return res;
207+
return cloneByNamePathList(props.model, nameList);
213208
}
214209
};
215210
const validateFields = (nameList?: NamePath[], options?: ValidateOptions) => {

components/form/utils/valueUtil.ts

+27
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { toArray } from './typeUtil';
22
import type { InternalNamePath, NamePath } from '../interface';
3+
import get from '../../vc-util/get';
4+
import set from '../../vc-util/set';
35

46
/**
57
* Convert name to internal supported format.
@@ -12,6 +14,21 @@ export function getNamePath(path: NamePath | null): InternalNamePath {
1214
return toArray(path);
1315
}
1416

17+
export function getValue<T>(store: T, namePath: InternalNamePath) {
18+
const value = get(store, namePath);
19+
return value;
20+
}
21+
22+
export function setValue<T>(
23+
store: T,
24+
namePath: InternalNamePath,
25+
value: any,
26+
removeIfUndefined = false,
27+
): T {
28+
const newStore = set(store, namePath, value, removeIfUndefined);
29+
return newStore;
30+
}
31+
1532
export function containsNamePath(namePathList: InternalNamePath[], namePath: InternalNamePath) {
1633
return namePathList && namePathList.some(path => matchNamePath(path, namePath));
1734
}
@@ -50,6 +67,16 @@ export function setValues<T>(store: T, ...restValues: T[]): T {
5067
);
5168
}
5269

70+
export function cloneByNamePathList<T>(store: T, namePathList: InternalNamePath[]): T {
71+
let newStore = {} as T;
72+
namePathList.forEach(namePath => {
73+
const value = getValue(store, namePath);
74+
newStore = setValue(newStore, namePath, value);
75+
});
76+
77+
return newStore;
78+
}
79+
5380
export function matchNamePath(
5481
namePath: InternalNamePath,
5582
changedNamePath: InternalNamePath | null,

components/vc-util/get.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export default function get(entity: any, path: (string | number)[]) {
2+
let current = entity;
3+
4+
for (let i = 0; i < path.length; i += 1) {
5+
if (current === null || current === undefined) {
6+
return undefined;
7+
}
8+
9+
current = current[path[i]];
10+
}
11+
12+
return current;
13+
}

components/vc-util/set.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import get from './get';
2+
3+
function internalSet<Entity = any, Output = Entity, Value = any>(
4+
entity: Entity,
5+
paths: (string | number)[],
6+
value: Value,
7+
removeIfUndefined: boolean,
8+
): Output {
9+
if (!paths.length) {
10+
return value as unknown as Output;
11+
}
12+
13+
const [path, ...restPath] = paths;
14+
15+
let clone: Output;
16+
if (!entity && typeof path === 'number') {
17+
clone = [] as unknown as Output;
18+
} else if (Array.isArray(entity)) {
19+
clone = [...entity] as unknown as Output;
20+
} else {
21+
clone = { ...entity } as unknown as Output;
22+
}
23+
24+
// Delete prop if `removeIfUndefined` and value is undefined
25+
if (removeIfUndefined && value === undefined && restPath.length === 1) {
26+
delete clone[path][restPath[0]];
27+
} else {
28+
clone[path] = internalSet(clone[path], restPath, value, removeIfUndefined);
29+
}
30+
31+
return clone;
32+
}
33+
34+
export default function set<Entity = any, Output = Entity, Value = any>(
35+
entity: Entity,
36+
paths: (string | number)[],
37+
value: Value,
38+
removeIfUndefined = false,
39+
): Output {
40+
// Do nothing if `removeIfUndefined` and parent object not exist
41+
if (
42+
paths.length &&
43+
removeIfUndefined &&
44+
value === undefined &&
45+
!get(entity, paths.slice(0, -1))
46+
) {
47+
return entity as unknown as Output;
48+
}
49+
50+
return internalSet(entity, paths, value, removeIfUndefined);
51+
}

0 commit comments

Comments
 (0)