Skip to content

Commit 298577b

Browse files
committedMay 7, 2023
fix(breaking): setValues should keep unspecified values closes #4231
1 parent 9540908 commit 298577b

File tree

3 files changed

+21
-23
lines changed

3 files changed

+21
-23
lines changed
 

‎.changeset/tame-comics-happen.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'vee-validate': patch
3+
---
4+
5+
setValues does not delete unspecified fields values

‎packages/vee-validate/src/types/forms.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ComputedRef, Ref } from 'vue';
22
import { MapValuesPathsToRefs, MaybeRef, GenericObject, MaybeRefOrLazy } from './common';
33
import { FieldValidationMetaInfo } from '../../../shared';
44
import { Path, PathValue } from './paths';
5+
import { PartialDeep } from 'type-fest';
56

67
export interface ValidationResult {
78
errors: string[];
@@ -148,7 +149,7 @@ export type GenericValidateFunction<TValue = unknown> = (
148149
) => boolean | string | Promise<boolean | string>;
149150

150151
export interface FormState<TValues> {
151-
values: TValues;
152+
values: PartialDeep<TValues>;
152153
errors: Partial<Record<Path<TValues>, string | undefined>>;
153154
touched: Partial<Record<Path<TValues>, boolean>>;
154155
submitCount: number;
@@ -168,7 +169,7 @@ export interface FormActions<TValues extends GenericObject, TOutput = TValues> {
168169
): void;
169170
setFieldError(field: Path<TValues>, message: string | string[] | undefined): void;
170171
setErrors(fields: FormErrors<TValues>): void;
171-
setValues<T extends Path<TValues>>(fields: Partial<Record<T, TValues[T]>>): void;
172+
setValues(fields: PartialDeep<TValues>): void;
172173
setFieldTouched(field: Path<TValues>, isTouched: boolean): void;
173174
setTouched(fields: Partial<Record<Path<TValues>, boolean>>): void;
174175
resetForm(state?: Partial<FormState<TValues>>): void;

‎packages/vee-validate/src/useForm.ts

+13-21
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ import {
6767
import { FormContextKey } from './symbols';
6868
import { validateTypedSchema, validateObjectSchema } from './validate';
6969
import { refreshInspector, registerFormWithDevTools } from './devtools';
70-
import { isCallable } from '../../shared';
70+
import { isCallable, merge } from '../../shared';
7171
import { getConfig } from './config';
72+
import { PartialDeep } from 'type-fest';
7273

7374
type FormSchema<TValues extends Record<string, unknown>> =
7475
| FlattenAndSetPathsType<TValues, GenericValidateFunction | string | GenericObject>
@@ -82,7 +83,7 @@ export interface FormOptions<
8283
| TypedSchema<TValues, TOutput>
8384
> {
8485
validationSchema?: MaybeRef<TSchema extends TypedSchema ? TypedSchema<TValues, TOutput> : any>;
85-
initialValues?: MaybeRef<Partial<TValues>>;
86+
initialValues?: MaybeRef<PartialDeep<TValues>>;
8687
initialErrors?: FlattenAndSetPathsType<TValues, string | undefined>;
8788
initialTouched?: FlattenAndSetPathsType<TValues, boolean>;
8889
validateOnMount?: boolean;
@@ -103,10 +104,6 @@ function resolveInitialValues<TValues extends GenericObject = GenericObject>(opt
103104
return deepCopy(providedValues) as TValues;
104105
}
105106

106-
// TODO: BIG FAT WORK TO DO:
107-
// Resets must happen here, the useField should not handle its resets unless called from there.
108-
// Field validators must not set their state, the forms must do that instead and process their own errors, unless no form exists
109-
110107
export function useForm<
111108
TValues extends GenericObject = GenericObject,
112109
TOutput = TValues,
@@ -158,7 +155,10 @@ export function useForm<
158155
const state = findPathState(path);
159156
if (state) {
160157
state.errors = normalizeErrorItem(paths[path]);
158+
return;
161159
}
160+
161+
extraErrorsBag.value[path as string] = normalizeErrorItem(paths[path]);
162162
});
163163
}
164164

@@ -544,16 +544,8 @@ export function useForm<
544544
/**
545545
* Sets multiple fields values
546546
*/
547-
function setValues(fields: Partial<TValues>) {
548-
// clean up old values
549-
keysOf(formValues).forEach(key => {
550-
delete formValues[key];
551-
});
552-
553-
// set up new values
554-
keysOf(fields).forEach(path => {
555-
setFieldValue(path as Path<TValues>, fields[path]);
556-
});
547+
function setValues(fields: PartialDeep<TValues>) {
548+
merge(formValues, fields);
557549

558550
// regenerate the arrays when the form values change
559551
fieldArrays.forEach(f => f && f.reset());
@@ -939,7 +931,7 @@ export function useForm<
939931
function useFormMeta<TValues extends Record<string, unknown>>(
940932
pathsState: Ref<PathState<unknown>[]>,
941933
currentValues: TValues,
942-
initialValues: MaybeRef<Partial<TValues>>,
934+
initialValues: MaybeRef<PartialDeep<TValues>>,
943935
errors: Ref<FormErrors<TValues>>
944936
) {
945937
const MERGE_STRATEGIES: Record<keyof Pick<FieldMeta<unknown>, 'touched' | 'pending' | 'valid'>, 'every' | 'some'> = {
@@ -990,18 +982,18 @@ function useFormInitialValues<TValues extends GenericObject>(
990982
formValues: TValues,
991983
opts?: FormOptions<TValues>
992984
) {
993-
const values = resolveInitialValues(opts);
985+
const values = resolveInitialValues(opts) as PartialDeep<TValues>;
994986
const providedValues = opts?.initialValues;
995987
// these are the mutable initial values as the fields are mounted/unmounted
996-
const initialValues = ref<Partial<TValues>>(values);
988+
const initialValues = ref<PartialDeep<TValues>>(values);
997989
// these are the original initial value as provided by the user initially, they don't keep track of conditional fields
998990
// this is important because some conditional fields will overwrite the initial values for other fields who had the same name
999991
// like array fields, any push/insert operation will overwrite the initial values because they "create new fields"
1000992
// so these are the values that the reset function should use
1001993
// these only change when the user explicitly changes the initial values or when the user resets them with new values.
1002-
const originalInitialValues = ref<Partial<TValues>>(deepCopy(values)) as Ref<Partial<TValues>>;
994+
const originalInitialValues = ref<PartialDeep<TValues>>(deepCopy(values)) as Ref<PartialDeep<TValues>>;
1003995

1004-
function setInitialValues(values: Partial<TValues>, updateFields = false) {
996+
function setInitialValues(values: PartialDeep<TValues>, updateFields = false) {
1005997
initialValues.value = deepCopy(values);
1006998
originalInitialValues.value = deepCopy(values);
1007999

0 commit comments

Comments
 (0)
Please sign in to comment.