Skip to content

Commit 36f6b9e

Browse files
committed
fix: reset form and field behaviors for unspecified values closes #4564
1 parent c1c6f39 commit 36f6b9e

File tree

5 files changed

+74
-6
lines changed

5 files changed

+74
-6
lines changed

.changeset/brave-squids-deliver.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'vee-validate': patch
3+
---
4+
5+
fix: reset form and field behaviors for unspecified values closes #4564

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ export interface PrivateFormContext<TValues extends GenericObject = GenericObjec
328328
stageInitialValue(path: string, value: unknown, updateOriginal?: boolean): void;
329329
unsetInitialValue(path: string): void;
330330
handleSubmit: HandleSubmitFactory<TValues, TOutput> & { withControlled: HandleSubmitFactory<TValues, TOutput> };
331-
setFieldInitialValue(path: string, value: unknown): void;
331+
setFieldInitialValue(path: string, value: unknown, updateOriginal?: boolean): void;
332332
createPathState<TPath extends Path<TValues>>(
333333
path: MaybeRef<TPath>,
334334
config?: Partial<PathStateConfig>,

packages/vee-validate/src/useFieldState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export function _useFieldValue<TValue = unknown>(
141141
return;
142142
}
143143

144-
form.stageInitialValue(unref(path), value, true);
144+
form.setFieldInitialValue(unref(path), value, true);
145145
}
146146

147147
const initialValue = computed(resolveInitialValue);

packages/vee-validate/src/useForm.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ export function useForm<
750750
pathState.__flags.pendingReset = true;
751751
}
752752

753-
setFieldInitialValue(field, deepCopy(newValue));
753+
setFieldInitialValue(field, deepCopy(newValue), true);
754754
setFieldValue(field, newValue as PathValue<TValues, typeof field>, false);
755755
setFieldTouched(field, state?.touched ?? false);
756756
setFieldError(field, state?.errors || []);
@@ -768,6 +768,7 @@ export function useForm<
768768
function resetForm(resetState?: Partial<FormState<TValues>>, opts?: ResetFormOpts) {
769769
let newValues = deepCopy(resetState?.values ? resetState.values : originalInitialValues.value);
770770
newValues = isTypedSchema(schema) && isCallable(schema.cast) ? schema.cast(newValues) : newValues;
771+
newValues = opts?.force ? newValues : merge(originalInitialValues.value, newValues);
771772
setInitialValues(newValues);
772773
mutateAllPathState(state => {
773774
state.__flags.pendingReset = true;
@@ -886,8 +887,11 @@ export function useForm<
886887
}
887888
}
888889

889-
function setFieldInitialValue(path: string, value: unknown) {
890+
function setFieldInitialValue(path: string, value: unknown, updateOriginal = false) {
890891
setInPath(initialValues.value, path, deepCopy(value));
892+
if (updateOriginal) {
893+
setInPath(originalInitialValues.value, path, deepCopy(value));
894+
}
891895
}
892896

893897
async function _validateSchema(): Promise<FormValidationResult<TValues, TOutput>> {

packages/vee-validate/tests/useForm.spec.ts

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
import { FieldMeta, FormContext, FormMeta, useField, useForm, defineRule, configure } from '@/vee-validate';
1+
import {
2+
FieldMeta,
3+
FormContext,
4+
FormMeta,
5+
useField,
6+
useForm,
7+
defineRule,
8+
configure,
9+
FieldContext,
10+
} from '@/vee-validate';
211
import { mountWithHoc, setValue, flushPromises, dispatchEvent } from './helpers';
312
import * as yup from 'yup';
413
import { onMounted, ref, Ref } from 'vue';
514
import { ModelComp, CustomModelComp } from './helpers/ModelComp';
6-
import { FieldContext } from '../dist/vee-validate';
715

816
describe('useForm()', () => {
917
const REQUIRED_MESSAGE = 'Field is required';
@@ -1292,4 +1300,55 @@ describe('useForm()', () => {
12921300
expect(form.values.lname).toBeUndefined();
12931301
expect(form.values.fname).toBe('test');
12941302
});
1303+
1304+
test('reset should not make unspecified values undefined', async () => {
1305+
let form!: FormContext<{ fname: string; lname: string }>;
1306+
1307+
mountWithHoc({
1308+
setup() {
1309+
form = useForm({
1310+
initialValues: { fname: '123', lname: '456' },
1311+
});
1312+
1313+
form.defineField('fname');
1314+
form.defineField('lname');
1315+
1316+
return {};
1317+
},
1318+
template: `
1319+
<div></div>
1320+
`,
1321+
});
1322+
1323+
await flushPromises();
1324+
1325+
form.resetForm({ values: { fname: 'test' } });
1326+
expect(form.values.lname).toBe('456');
1327+
expect(form.values.fname).toBe('test');
1328+
});
1329+
1330+
test('reset field should make the dirty state false', async () => {
1331+
let form!: FormContext<{ fname: string; lname: string }>;
1332+
1333+
mountWithHoc({
1334+
setup() {
1335+
form = useForm({
1336+
initialValues: { fname: '123', lname: '456' },
1337+
});
1338+
1339+
form.defineField('fname');
1340+
form.defineField('lname');
1341+
1342+
return {};
1343+
},
1344+
template: `
1345+
<div></div>
1346+
`,
1347+
});
1348+
1349+
await flushPromises();
1350+
1351+
form.resetField('fname', { value: 'test' });
1352+
expect(form.meta.value.dirty).toBe(false);
1353+
});
12951354
});

0 commit comments

Comments
 (0)