Skip to content

Commit

Permalink
FIX: avoid setting the absent value to checkboxes without unchecked v…
Browse files Browse the repository at this point in the history
…alue closes #3424
  • Loading branch information
logaretm committed Jul 31, 2021
1 parent b662c3d commit 3824103
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 5 deletions.
9 changes: 7 additions & 2 deletions packages/vee-validate/src/Field.ts
Expand Up @@ -3,7 +3,7 @@ import { getConfig } from './config';
import { useField } from './useField';
import { normalizeChildren, hasCheckedAttr, shouldHaveValueBinding, isPropPresent } from './utils';
import { toNumber } from '../../shared';
import { EMPTY_VALUE } from './symbols';
import { IS_ABSENT } from './symbols';

interface ValidationTriggersProps {
validateOnMount: boolean;
Expand Down Expand Up @@ -64,7 +64,7 @@ export const Field = defineComponent({
},
modelValue: {
type: null,
default: EMPTY_VALUE,
default: IS_ABSENT,
},
modelModifiers: {
type: null,
Expand Down Expand Up @@ -162,6 +162,11 @@ export const Field = defineComponent({

const modelValue = toRef(props, 'modelValue');
watch(modelValue, newModelValue => {
// Don't attempt to sync absent values
if ((newModelValue as any) === IS_ABSENT && value.value === undefined) {
return;
}

if (newModelValue !== applyModifiers(value.value, props.modelModifiers)) {
value.value = newModelValue;
validateField();
Expand Down
2 changes: 1 addition & 1 deletion packages/vee-validate/src/symbols.ts
Expand Up @@ -12,4 +12,4 @@ export const FormInitialValuesKey: InjectionKey<ComputedRef<Record<string, unkno

export const FieldContextKey: InjectionKey<PrivateFieldContext<unknown>> = Symbol('vee-validate-field-instance');

export const EMPTY_VALUE = Symbol('Default empty value');
export const IS_ABSENT = Symbol('Default empty value');
4 changes: 2 additions & 2 deletions packages/vee-validate/src/utils/assertions.ts
@@ -1,6 +1,6 @@
import { Locator, YupValidator } from '../types';
import { isCallable, isObject } from '../../../shared';
import { EMPTY_VALUE } from '../symbols';
import { IS_ABSENT } from '../symbols';

export function isLocator(value: unknown): value is Locator {
return isCallable(value) && !!(value as Locator).__locatorRef;
Expand Down Expand Up @@ -102,5 +102,5 @@ export function isEvent(evt: unknown): evt is Event {
}

export function isPropPresent(obj: Record<string, unknown>, prop: string) {
return prop in obj && obj[prop] !== EMPTY_VALUE;
return prop in obj && obj[prop] !== IS_ABSENT;
}
28 changes: 28 additions & 0 deletions packages/vee-validate/tests/Form.spec.ts
Expand Up @@ -2177,4 +2177,32 @@ describe('<Form />', () => {
expect(fieldError.textContent).toBe(REQUIRED_MESSAGE);
expect(meta.textContent).toBe('true');
});

// 3424
test('Checkbox with v-model should not propagate the empty value symbol', async () => {
const value = ref('');
mountWithHoc({
setup() {
return {
value,
};
},
template: `
<VForm>
<Field name="check" type="checkbox" v-model="value" value="CHECKED" />
</VForm>
`,
});

await flushPromises();
const input = document.querySelector('input') as HTMLInputElement;
setChecked(input, true);
await flushPromises();
expect(value.value).toBe('CHECKED');

setChecked(input, false);
await flushPromises();

expect(value.value).toBe(undefined);
});
});

0 comments on commit 3824103

Please sign in to comment.