Skip to content

Commit 2d8143f

Browse files
authored
feat: added composition setter functions (#4397)
1 parent 61b34ca commit 2d8143f

16 files changed

+637
-3
lines changed

.changeset/spicy-balloons-dream.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'vee-validate': minor
3+
---
4+
5+
feat: added composition setter functions

packages/vee-validate/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,10 @@ export { useFormValues } from './useFormValues';
5454
export { useFormErrors } from './useFormErrors';
5555
export { useFieldError } from './useFieldError';
5656
export { useSubmitForm } from './useSubmitForm';
57+
export { useSetFieldError } from './useSetFieldError';
58+
export { useSetFieldTouched } from './useSetFieldTouched';
59+
export { useSetFieldValue } from './useSetFieldValue';
60+
export { useSetFormErrors } from './useSetFormErrors';
61+
export { useSetFormTouched } from './useSetFormTouched';
62+
export { useSetFormValues } from './useSetFormValues';
5763
export { FormContextKey, FieldContextKey, IS_ABSENT } from './symbols';

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ export interface PrivateFieldContext<TValue = unknown> {
143143
setState(state: Partial<FieldState<TValue>>): void;
144144
setTouched(isTouched: boolean): void;
145145
setErrors(message: string | string[]): void;
146-
setValue(value: TValue): void;
146+
setValue(value: TValue, shouldValidate?: boolean): void;
147147
}
148148

149149
export type FieldContext<TValue = unknown> = Omit<PrivateFieldContext<TValue>, 'id' | 'instances'>;
@@ -170,7 +170,7 @@ export interface FormActions<TValues extends GenericObject, TOutput = TValues> {
170170
setErrors(fields: Partial<FlattenAndSetPathsType<TValues, string | string[] | undefined>>): void;
171171
setValues(fields: PartialDeep<TValues>, shouldValidate?: boolean): void;
172172
setFieldTouched(field: Path<TValues>, isTouched: boolean): void;
173-
setTouched(fields: Partial<Record<Path<TValues>, boolean>>): void;
173+
setTouched(fields: Partial<Record<Path<TValues>, boolean>> | boolean): void;
174174
resetForm(state?: Partial<FormState<TValues>>): void;
175175
resetField(field: Path<TValues>, state?: Partial<FieldState>): void;
176176
}

packages/vee-validate/src/useForm.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,15 @@ export function useForm<
685685
/**
686686
* Sets the touched meta state on multiple fields
687687
*/
688-
function setTouched(fields: Partial<FlattenAndSetPathsType<TValues, boolean>>) {
688+
function setTouched(fields: Partial<FlattenAndSetPathsType<TValues, boolean>> | boolean) {
689+
if (typeof fields === 'boolean') {
690+
mutateAllPathState(state => {
691+
state.touched = fields;
692+
});
693+
694+
return;
695+
}
696+
689697
keysOf(fields).forEach(field => {
690698
setFieldTouched(field, !!fields[field]);
691699
});
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { inject, MaybeRefOrGetter, toValue } from 'vue';
2+
import { FieldContextKey, FormContextKey } from './symbols';
3+
import { injectWithSelf, warn } from './utils';
4+
5+
/**
6+
* Sets a field's error message
7+
*/
8+
export function useSetFieldError(path?: MaybeRefOrGetter<string>) {
9+
const form = injectWithSelf(FormContextKey);
10+
// We don't want to use self injected context as it doesn't make sense
11+
const field = path ? undefined : inject(FieldContextKey);
12+
13+
return function setFieldError(message: string | string[] | undefined) {
14+
if (path && form) {
15+
form.setFieldError(toValue(path), message);
16+
}
17+
18+
if (field) {
19+
field.setErrors(message || []);
20+
}
21+
22+
if (__DEV__) {
23+
warn(`Could not set error for unknown field with path "${toValue(path)}"`);
24+
}
25+
};
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { inject, MaybeRefOrGetter, toValue } from 'vue';
2+
import { FieldContextKey, FormContextKey } from './symbols';
3+
import { injectWithSelf, warn } from './utils';
4+
5+
/**
6+
* Sets a field's touched meta state
7+
*/
8+
export function useSetFieldTouched(path?: MaybeRefOrGetter<string>) {
9+
const form = injectWithSelf(FormContextKey);
10+
// We don't want to use self injected context as it doesn't make sense
11+
const field = path ? undefined : inject(FieldContextKey);
12+
13+
return function setFieldTouched(touched: boolean) {
14+
if (path && form) {
15+
form.setFieldTouched(toValue(path), touched);
16+
}
17+
18+
if (field) {
19+
field.setTouched(touched);
20+
}
21+
22+
if (__DEV__) {
23+
warn(`Could not set touched meta for unknown field with path "${toValue(path)}"`);
24+
}
25+
};
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { inject, MaybeRefOrGetter, toValue } from 'vue';
2+
import { FieldContextKey, FormContextKey } from './symbols';
3+
import { injectWithSelf, warn } from './utils';
4+
5+
/**
6+
* Sets a field's value
7+
*/
8+
export function useSetFieldValue<TValue = unknown>(path?: MaybeRefOrGetter<string>) {
9+
const form = injectWithSelf(FormContextKey);
10+
// We don't want to use self injected context as it doesn't make sense
11+
const field = path ? undefined : inject(FieldContextKey);
12+
13+
return function setFieldValue(value: TValue, shouldValidate = true) {
14+
if (path && form) {
15+
form.setFieldValue(toValue(path), value, shouldValidate);
16+
}
17+
18+
if (field) {
19+
field.setValue(value, shouldValidate);
20+
}
21+
22+
if (__DEV__) {
23+
warn(`Could not set value for unknown field with path "${toValue(path)}"`);
24+
}
25+
};
26+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { FormContextKey } from './symbols';
2+
import { injectWithSelf, warn } from './utils';
3+
4+
/**
5+
* Sets multiple fields errors
6+
*/
7+
export function useSetFormErrors() {
8+
const form = injectWithSelf(FormContextKey);
9+
10+
function setFormErrors(fields: Record<string, string | string[] | undefined>) {
11+
if (form) {
12+
form.setErrors(fields);
13+
}
14+
15+
if (__DEV__) {
16+
warn(
17+
`Could not set errors because a form was not detected, did you forget to use "useForm" in a parent component?`,
18+
);
19+
}
20+
}
21+
22+
return setFormErrors;
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { FormContextKey } from './symbols';
2+
import { injectWithSelf, warn } from './utils';
3+
4+
/**
5+
* Sets multiple fields touched or all fields in the form
6+
*/
7+
export function useSetFormTouched() {
8+
const form = injectWithSelf(FormContextKey);
9+
10+
function setFormTouched(fields: Record<string, boolean> | boolean) {
11+
if (form) {
12+
form.setTouched(fields);
13+
}
14+
15+
if (__DEV__) {
16+
warn(
17+
`Could not set touched state because a form was not detected, did you forget to use "useForm" in a parent component?`,
18+
);
19+
}
20+
}
21+
22+
return setFormTouched;
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { FormContextKey } from './symbols';
2+
import { injectWithSelf, warn } from './utils';
3+
4+
/**
5+
* Sets multiple fields values
6+
*/
7+
export function useSetFormValues() {
8+
const form = injectWithSelf(FormContextKey);
9+
10+
function setFormValues(fields: Record<string, unknown>) {
11+
if (form) {
12+
form.setValues(fields);
13+
}
14+
15+
if (__DEV__) {
16+
warn(
17+
`Could not set form values because a form was not detected, did you forget to use "useForm" in a parent component?`,
18+
);
19+
}
20+
}
21+
22+
return setFormValues;
23+
}

0 commit comments

Comments
 (0)