Skip to content

Commit

Permalink
fix: do not warn if a form or a field was resolved closes #4399
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Aug 5, 2023
1 parent 1df2147 commit 2ff045c
Show file tree
Hide file tree
Showing 21 changed files with 83 additions and 29 deletions.
5 changes: 5 additions & 0 deletions .changeset/orange-crabs-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vee-validate': patch
---

fix: do not warn if a form or a field was resolved closes #4399
6 changes: 3 additions & 3 deletions packages/vee-validate/src/useFieldError.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { computed, inject, unref, MaybeRef } from 'vue';
import { computed, inject, MaybeRefOrGetter, toValue } from 'vue';
import { FieldContextKey, FormContextKey } from './symbols';
import { injectWithSelf } from './utils';

/**
* Gives access to a single field error
*/
export function useFieldError(path?: MaybeRef<string>) {
export function useFieldError(path?: MaybeRefOrGetter<string>) {
const form = injectWithSelf(FormContextKey);
// We don't want to use self injected context as it doesn't make sense
const field = path ? undefined : inject(FieldContextKey);

return computed<string | undefined>(() => {
if (path) {
return form?.errors.value[unref(path)];
return form?.errors.value[toValue(path)];
}

return field?.errorMessage.value;
Expand Down
8 changes: 4 additions & 4 deletions packages/vee-validate/src/useFieldValue.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { computed, inject, unref, MaybeRef } from 'vue';
import { computed, inject, MaybeRefOrGetter, toValue } from 'vue';
import { FieldContextKey, FormContextKey } from './symbols';
import { getFromPath, injectWithSelf } from './utils';

/**
* Gives access to a field's current value
*/
export function useFieldValue<TValue = unknown>(path?: MaybeRef<string>) {
export function useFieldValue<TValue = unknown>(path?: MaybeRefOrGetter<string>) {
const form = injectWithSelf(FormContextKey);
// We don't want to use self injected context as it doesn't make sense
const field = path ? undefined : inject(FieldContextKey);

return computed(() => {
if (path) {
return getFromPath(form?.values, unref(path)) as TValue;
return getFromPath(form?.values, toValue(path)) as TValue;
}

return unref(field?.value) as TValue;
return toValue(field?.value) as TValue;
});
}
4 changes: 2 additions & 2 deletions packages/vee-validate/src/useIsFieldDirty.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { computed, MaybeRef } from 'vue';
import { computed, MaybeRefOrGetter } from 'vue';
import { resolveFieldOrPathState } from './utils';

/**
* If a field is dirty or not
*/
export function useIsFieldDirty(path?: MaybeRef<string>) {
export function useIsFieldDirty(path?: MaybeRefOrGetter<string>) {
const fieldOrPath = resolveFieldOrPathState(path);

return computed(() => {
Expand Down
4 changes: 2 additions & 2 deletions packages/vee-validate/src/useIsFieldTouched.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { computed, MaybeRef } from 'vue';
import { MaybeRefOrGetter, computed } from 'vue';
import { resolveFieldOrPathState } from './utils';

/**
* If a field is touched or not
*/
export function useIsFieldTouched(path?: MaybeRef<string>) {
export function useIsFieldTouched(path?: MaybeRefOrGetter<string>) {
const fieldOrPath = resolveFieldOrPathState(path);

return computed(() => {
Expand Down
4 changes: 2 additions & 2 deletions packages/vee-validate/src/useIsFieldValid.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { computed, MaybeRef } from 'vue';
import { computed, MaybeRefOrGetter } from 'vue';
import { resolveFieldOrPathState } from './utils';

/**
* If a field is validated and is valid
*/
export function useIsFieldValid(path?: MaybeRef<string>) {
export function useIsFieldValid(path?: MaybeRefOrGetter<string>) {
const fieldOrPath = resolveFieldOrPathState(path);

return computed(() => {
Expand Down
8 changes: 7 additions & 1 deletion packages/vee-validate/src/useSetFieldError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,20 @@ export function useSetFieldError(path?: MaybeRefOrGetter<string>) {
return function setFieldError(message: string | string[] | undefined) {
if (path && form) {
form.setFieldError(toValue(path), message);
return;
}

if (field) {
field.setErrors(message || []);
return;
}

if (__DEV__) {
warn(`Could not set error for unknown field with path "${toValue(path)}"`);
warn(
`Could not set error message since there is no form context or a field named "${toValue(
path,
)}", did you forget to call "useField" or "useForm"?`,
);
}
};
}
8 changes: 7 additions & 1 deletion packages/vee-validate/src/useSetFieldTouched.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,20 @@ export function useSetFieldTouched(path?: MaybeRefOrGetter<string>) {
return function setFieldTouched(touched: boolean) {
if (path && form) {
form.setFieldTouched(toValue(path), touched);
return;
}

if (field) {
field.setTouched(touched);
return;
}

if (__DEV__) {
warn(`Could not set touched meta for unknown field with path "${toValue(path)}"`);
warn(
`Could not set touched state since there is no form context or a field named "${toValue(
path,
)}", did you forget to call "useField" or "useForm"?`,
);
}
};
}
8 changes: 7 additions & 1 deletion packages/vee-validate/src/useSetFieldValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,20 @@ export function useSetFieldValue<TValue = unknown>(path?: MaybeRefOrGetter<strin
return function setFieldValue(value: TValue, shouldValidate = true) {
if (path && form) {
form.setFieldValue(toValue(path), value, shouldValidate);
return;
}

if (field) {
field.setValue(value, shouldValidate);
return;
}

if (__DEV__) {
warn(`Could not set value for unknown field with path "${toValue(path)}"`);
warn(
`Could not set value since there is no form context or a field named "${toValue(
path,
)}", did you forget to call "useField" or "useForm"?`,
);
}
};
}
1 change: 1 addition & 0 deletions packages/vee-validate/src/useSetFormErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function useSetFormErrors() {
function setFormErrors(fields: Record<string, string | string[] | undefined>) {
if (form) {
form.setErrors(fields);
return;
}

if (__DEV__) {
Expand Down
1 change: 1 addition & 0 deletions packages/vee-validate/src/useSetFormTouched.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function useSetFormTouched() {
function setFormTouched(fields: Record<string, boolean> | boolean) {
if (form) {
form.setTouched(fields);
return;
}

if (__DEV__) {
Expand Down
1 change: 1 addition & 0 deletions packages/vee-validate/src/useSetFormValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function useSetFormValues() {
function setFormValues(fields: Record<string, unknown>) {
if (form) {
form.setValues(fields);
return;
}

if (__DEV__) {
Expand Down
6 changes: 3 additions & 3 deletions packages/vee-validate/src/useValidateField.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { inject, unref, MaybeRef } from 'vue';
import { MaybeRefOrGetter, inject, toValue, unref } from 'vue';
import { FieldContextKey, FormContextKey } from './symbols';
import { ValidationResult } from './types';
import { injectWithSelf, warn } from './utils';

/**
* Validates a single field
*/
export function useValidateField(path?: MaybeRef<string>) {
export function useValidateField(path?: MaybeRefOrGetter<string>) {
const form = injectWithSelf(FormContextKey);
const field = path ? undefined : inject(FieldContextKey);

Expand All @@ -16,7 +16,7 @@ export function useValidateField(path?: MaybeRef<string>) {
}

if (form && path) {
return form?.validateField(unref(path));
return form?.validateField(toValue(path));
}

warn(`field with name ${unref(path)} was not found`);
Expand Down
10 changes: 5 additions & 5 deletions packages/vee-validate/src/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {
InjectionKey,
ref,
Ref,
unref,
warn as vueWarning,
watch,
MaybeRef,
nextTick,
MaybeRefOrGetter,
toValue,
} from 'vue';
import { klona as deepCopy } from 'klona/full';
import { isIndex, isNullOrUndefined, isObject, toNumber } from '../../../shared';
Expand Down Expand Up @@ -305,13 +305,13 @@ export function normalizeErrorItem(message: string | string[] | null | undefined
return Array.isArray(message) ? message : message ? [message] : [];
}

export function resolveFieldOrPathState(path?: MaybeRef<string>) {
export function resolveFieldOrPathState(path?: MaybeRefOrGetter<string>) {
const form = injectWithSelf(FormContextKey);
const state = path ? computed(() => form?.getPathState(unref(path))) : undefined;
const state = path ? computed(() => form?.getPathState(toValue(path))) : undefined;
const field = path ? undefined : inject(FieldContextKey);

if (!field && !state?.value) {
warn(`field with name ${unref(path)} was not found`);
warn(`field with name ${toValue(path)} was not found`);
}

return state || field;
Expand Down
4 changes: 3 additions & 1 deletion packages/vee-validate/tests/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ export function mount(component: Record<string, any>) {

document.body.innerHTML = `<div id="app"></div>`;

return app.mount('#app');
const vm = app.mount('#app');

return vm;
}

export function mountWithHoc(component: Record<string, any>) {
Expand Down
7 changes: 5 additions & 2 deletions packages/vee-validate/tests/useSetFieldError.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import { defineComponent } from 'vue';

describe('useSetFieldError()', () => {
test('sets a single field error message', async () => {
const spy = vi.spyOn(console, 'warn').mockImplementation(() => {
// NOOP
});
let setError!: ReturnType<typeof useSetFieldError>;

mountWithHoc({
setup() {
useForm();
Expand All @@ -29,6 +31,8 @@ describe('useSetFieldError()', () => {
setError(msg);
await flushPromises();
expect(error?.textContent).toBe(msg);
expect(spy).not.toHaveBeenCalled();
spy.mockRestore();
});

test('sets a single field error message in a child component without specifying a path', async () => {
Expand Down Expand Up @@ -75,7 +79,6 @@ describe('useSetFieldError()', () => {

mountWithHoc({
setup() {
useForm();
setError = useSetFieldError('something');

return {};
Expand Down
6 changes: 5 additions & 1 deletion packages/vee-validate/tests/useSetFieldTouched.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { defineComponent } from 'vue';

describe('useSetFieldTouched()', () => {
test('sets a single field touched status', async () => {
const spy = vi.spyOn(console, 'warn').mockImplementation(() => {
// NOOP
});
let setTouched!: ReturnType<typeof useSetFieldTouched>;
mountWithHoc({
setup() {
Expand All @@ -26,6 +29,8 @@ describe('useSetFieldTouched()', () => {
setTouched(true);
await flushPromises();
expect(touched?.textContent).toBe('true');
expect(spy).not.toHaveBeenCalled();
spy.mockRestore();
});

test('sets a single field isTouched status in child components without path prop', async () => {
Expand Down Expand Up @@ -73,7 +78,6 @@ describe('useSetFieldTouched()', () => {

mountWithHoc({
setup() {
useForm();
setTouched = useSetFieldTouched('something');

return {};
Expand Down
6 changes: 5 additions & 1 deletion packages/vee-validate/tests/useSetFieldValue.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { defineComponent } from 'vue';

describe('useSetFieldTouched()', () => {
test('sets a single field value', async () => {
const spy = vi.spyOn(console, 'warn').mockImplementation(() => {
// NOOP
});
let setValue!: ReturnType<typeof useSetFieldValue>;
mountWithHoc({
setup() {
Expand All @@ -26,6 +29,8 @@ describe('useSetFieldTouched()', () => {
setValue('test 123');
await flushPromises();
expect(valueSpan?.textContent).toBe('test 123');
expect(spy).not.toHaveBeenCalled();
spy.mockRestore();
});

test('sets a single field value in child components without path prop', async () => {
Expand Down Expand Up @@ -74,7 +79,6 @@ describe('useSetFieldTouched()', () => {

mountWithHoc({
setup() {
useForm();
setValue = useSetFieldValue('something');

return {};
Expand Down
5 changes: 5 additions & 0 deletions packages/vee-validate/tests/useSetFormErrors.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ describe('useSetFormErrors()', () => {
const REQUIRED_MESSAGE = 'Field is required';

test('sets multiple fields errors', async () => {
const spy = vi.spyOn(console, 'warn').mockImplementation(() => {
// NOOP
});
let setErrors!: ReturnType<typeof useSetFormErrors>;
mountWithHoc({
setup() {
Expand All @@ -25,6 +28,8 @@ describe('useSetFormErrors()', () => {
setErrors({ test: REQUIRED_MESSAGE });
await flushPromises();
expect(error?.textContent).toBe(REQUIRED_MESSAGE);
expect(spy).not.toHaveBeenCalled();
spy.mockRestore();
});

test('warns if form is not found', async () => {
Expand Down
5 changes: 5 additions & 0 deletions packages/vee-validate/tests/useSetFormTouched.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { mountWithHoc, flushPromises } from './helpers';

describe('useSetFormTouched()', () => {
test('sets multiple fields touched state', async () => {
const spy = vi.spyOn(console, 'warn').mockImplementation(() => {
// NOOP
});
let setTouched!: ReturnType<typeof useSetFormTouched>;
mountWithHoc({
setup() {
Expand All @@ -29,6 +32,8 @@ describe('useSetFormTouched()', () => {
await flushPromises();
expect(touched1?.textContent).toBe('true');
expect(touched2?.textContent).toBe('false');
expect(spy).not.toHaveBeenCalled();
spy.mockRestore();
});

test('sets all fields touched state', async () => {
Expand Down
5 changes: 5 additions & 0 deletions packages/vee-validate/tests/useSetFormValues.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { mountWithHoc, flushPromises } from './helpers';

describe('useSetFormValues()', () => {
test('sets form values', async () => {
const spy = vi.spyOn(console, 'warn').mockImplementation(() => {
// NOOP
});
let setValues!: ReturnType<typeof useSetFormValues>;
mountWithHoc({
setup() {
Expand Down Expand Up @@ -30,6 +33,8 @@ describe('useSetFormValues()', () => {
await flushPromises();
expect(value1?.textContent).toBe('test1');
expect(value2?.textContent).toBe('test2');
expect(spy).not.toHaveBeenCalled();
spy.mockRestore();
});

test('warns if form is not found', async () => {
Expand Down

0 comments on commit 2ff045c

Please sign in to comment.