Skip to content

Commit

Permalink
feat: deprecate reactive initial values closes #4402
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Nov 18, 2023
1 parent 95b701f commit bbecc97
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 105 deletions.
5 changes: 5 additions & 0 deletions .changeset/metal-bags-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vee-validate': minor
---

feat: deprecate reactive initial values closes #4402
3 changes: 1 addition & 2 deletions packages/vee-validate/src/Form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ const FormImpl = /** #__PURE__ */ defineComponent({
},
},
setup(props, ctx) {
const initialValues = toRef(props, 'initialValues');
const validationSchema = toRef(props, 'validationSchema');
const keepValues = toRef(props, 'keepValues');

Expand All @@ -104,7 +103,7 @@ const FormImpl = /** #__PURE__ */ defineComponent({
resetField,
} = useForm({
validationSchema: validationSchema.value ? validationSchema : undefined,
initialValues,
initialValues: props.initialValues,
initialErrors: props.initialErrors,
initialTouched: props.initialTouched,
validateOnMount: props.validateOnMount,
Expand Down
19 changes: 2 additions & 17 deletions packages/vee-validate/src/useForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export interface FormOptions<
| TypedSchema<TValues, TOutput>,
> {
validationSchema?: MaybeRef<TSchema extends TypedSchema ? TypedSchema<TValues, TOutput> : any>;
initialValues?: MaybeRef<PartialDeep<TValues> | undefined | null>;
initialValues?: PartialDeep<TValues> | undefined | null;
initialErrors?: FlattenAndSetPathsType<TValues, string | undefined>;
initialTouched?: FlattenAndSetPathsType<TValues, boolean>;
validateOnMount?: boolean;
Expand All @@ -98,7 +98,7 @@ let FORM_COUNTER = 0;
const PRIVATE_PATH_STATE_KEYS: (keyof PathState)[] = ['bails', 'fieldsCount', 'id', 'multiple', 'type', 'validate'];

function resolveInitialValues<TValues extends GenericObject = GenericObject>(opts?: FormOptions<TValues>): TValues {
const providedValues = unref(opts?.initialValues) || {};
const providedValues = opts?.initialValues || {};
const schema = unref(opts?.validationSchema);
if (schema && isTypedSchema(schema) && isCallable(schema.cast)) {
return deepCopy(schema.cast(providedValues) || {});
Expand Down Expand Up @@ -1144,7 +1144,6 @@ function useFormInitialValues<TValues extends GenericObject>(
opts?: FormOptions<TValues>,
) {
const values = resolveInitialValues(opts) as PartialDeep<TValues>;
const providedValues = opts?.initialValues;
// these are the mutable initial values as the fields are mounted/unmounted
const initialValues = ref(values) as Ref<PartialDeep<TValues>>;
// these are the original initial value as provided by the user initially, they don't keep track of conditional fields
Expand Down Expand Up @@ -1177,20 +1176,6 @@ function useFormInitialValues<TValues extends GenericObject>(
});
}

if (isRef(providedValues)) {
watch(
providedValues,
value => {
if (value) {
setInitialValues(value, true);
}
},
{
deep: true,
},
);
}

return {
initialValues,
originalInitialValues,
Expand Down
87 changes: 1 addition & 86 deletions packages/vee-validate/tests/Form.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineRule, useField, Form, Field, useIsValidating } from '@/vee-validate';
import { mountWithHoc, setValue, setChecked, dispatchEvent, flushPromises } from './helpers';
import * as yup from 'yup';
import { computed, defineComponent, onErrorCaptured, reactive, ref, Ref } from 'vue';
import { computed, defineComponent, onErrorCaptured, ref, Ref } from 'vue';
import { InvalidSubmissionContext } from '../src/types';

describe('<Form />', () => {
Expand Down Expand Up @@ -204,91 +204,6 @@ describe('<Form />', () => {
expect(input.value).toBe(initialValues.field);
});

test('initial values can be reactive and will update non-touched fields', async () => {
let initialValues!: Record<string, any>;

const wrapper = mountWithHoc({
setup() {
initialValues = reactive({
field1: 'hello',
field2: 'hi',
});

return {
initialValues,
};
},
template: `
<VForm :initialValues="initialValues">
<Field rules="required" name="field1" />
<Field rules="required" name="field2" />
<button id="submit">Submit</button>
</VForm>
`,
});

const inputs = wrapper.$el.querySelectorAll('input');

await flushPromises();
setValue(inputs[0], '12');
dispatchEvent(inputs[0], 'blur');
await flushPromises();
initialValues.field1 = 'new';
initialValues.field2 = 'tada';
await flushPromises();

// this was not updated because it was changed by user
expect(inputs[0].value).not.toBe(initialValues.field1);

// this is updated because it wasn't changed by user
expect(inputs[1].value).toBe(initialValues.field2);
});

test('initial values can be refs and will update non-touched fields', async () => {
let initialValues!: Record<string, any>;

const wrapper = mountWithHoc({
setup() {
initialValues = ref({
field1: 'hello',
field2: 'hi',
});

return {
initialValues,
};
},
template: `
<VForm :initialValues="initialValues">
<Field rules="required" name="field1" />
<Field rules="required" name="field2" />
<button id="submit">Submit</button>
</VForm>
`,
});

const inputs = wrapper.$el.querySelectorAll('input');

await flushPromises();
setValue(inputs[0], '12');
dispatchEvent(inputs[0], 'blur');
await flushPromises();
initialValues.value = {
field1: 'new',
field2: 'tada',
};

await flushPromises();

// this was not updated because it was changed by user
expect(inputs[0].value).not.toBe(initialValues.value.field1);

// this is updated because it wasn't changed by user
expect(inputs[1].value).toBe(initialValues.value.field2);
});

test('having no submit listener will submit the form natively', async () => {
const submitMock = vi.fn();
const wrapper = mountWithHoc({
Expand Down

0 comments on commit bbecc97

Please sign in to comment.