Skip to content

Commit af910c3

Browse files
committed
feat: added unchecked-value prop to the field component
1 parent 3a9cc7f commit af910c3

4 files changed

Lines changed: 46 additions & 6 deletions

File tree

packages/vee-validate/src/Field.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,16 @@ export const Field = defineComponent({
5555
type: String,
5656
default: undefined,
5757
},
58+
uncheckedValue: {
59+
type: null,
60+
default: undefined,
61+
},
5862
},
5963
setup(props, ctx) {
6064
const rules = toRef(props, 'rules');
6165
const name = toRef(props, 'name');
6266
const label = toRef(props, 'label');
67+
const uncheckedValue = toRef(props, 'uncheckedValue');
6368

6469
const {
6570
errors,
@@ -88,6 +93,7 @@ export const Field = defineComponent({
8893
: ctx.attrs.value,
8994
// Only for checkboxes and radio buttons
9095
valueProp: ctx.attrs.value,
96+
uncheckedValue,
9197
label,
9298
validateOnValueUpdate: false,
9399
});

packages/vee-validate/src/useField.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface FieldOptions {
3232
bails?: boolean;
3333
type?: string;
3434
valueProp?: MaybeReactive<any>;
35+
uncheckedValue?: MaybeReactive<any>;
3536
label?: MaybeReactive<string>;
3637
}
3738

@@ -51,10 +52,16 @@ let ID_COUNTER = 0;
5152
*/
5253
export function useField(name: MaybeReactive<string>, rules?: RuleExpression, opts?: Partial<FieldOptions>) {
5354
const fid = ID_COUNTER >= Number.MAX_SAFE_INTEGER ? 0 : ++ID_COUNTER;
54-
const { initialValue, validateOnMount, bails, type, valueProp, label, validateOnValueUpdate } = normalizeOptions(
55-
unref(name),
56-
opts
57-
);
55+
const {
56+
initialValue,
57+
validateOnMount,
58+
bails,
59+
type,
60+
valueProp,
61+
label,
62+
validateOnValueUpdate,
63+
uncheckedValue,
64+
} = normalizeOptions(unref(name), opts);
5865

5966
const form = injectWithSelf(FormSymbol);
6067
const {
@@ -153,6 +160,7 @@ export function useField(name: MaybeReactive<string>, rules?: RuleExpression, op
153160
errorMessage,
154161
type,
155162
valueProp,
163+
uncheckedValue,
156164
checked,
157165
idx: -1,
158166
resetField,

packages/vee-validate/src/useForm.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export function useForm<TValues extends Record<string, any> = Record<string, any
148148
let newValue = value;
149149
// Single Checkbox
150150
if (fieldInstance?.type === 'checkbox') {
151-
newValue = getFromPath(formValues, field as string) === value ? undefined : value;
151+
newValue = getFromPath(formValues, field as string) === value ? fieldInstance.uncheckedValue : value;
152152
}
153153

154154
setInPath(formValues, field as string, newValue);

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import flushPromises from 'flush-promises';
22
import { defineRule, configure } from '@/vee-validate';
3-
import { mountWithHoc, setValue, dispatchEvent } from './helpers';
3+
import { mountWithHoc, setValue, dispatchEvent, setChecked } from './helpers';
44
import * as yup from 'yup';
55
import { ref, Ref } from 'vue';
66

@@ -816,4 +816,30 @@ describe('<Field />', () => {
816816
dispatchEvent(input as HTMLInputElement, 'blur');
817817
expect(onBlur).toHaveBeenCalledTimes(1);
818818
});
819+
820+
test('can customize checkboxes unchecked value', async () => {
821+
const spy = jest.fn();
822+
const wrapper = mountWithHoc({
823+
setup() {
824+
return { onSubmit: spy };
825+
},
826+
template: `
827+
<VForm @submit="onSubmit">
828+
<Field name="terms" as="input" type="checkbox" :unchecked-value="false" :value="true" /> Coffee
829+
830+
<button type="submit">Submit</button>
831+
</VForm>
832+
`,
833+
});
834+
835+
await flushPromises();
836+
const input = wrapper.$el.querySelector('input');
837+
setChecked(input, true);
838+
await flushPromises();
839+
setChecked(input, false);
840+
await flushPromises();
841+
wrapper.$el.querySelector('button').click();
842+
await flushPromises();
843+
expect(spy).toHaveBeenCalledWith(expect.objectContaining({ terms: false }), expect.anything());
844+
});
819845
});

0 commit comments

Comments
 (0)