Skip to content

Commit

Permalink
fix: added a symbol to detect non passed props with Vue 3.1.x (#3295)
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed May 8, 2021
1 parent b778970 commit 0663539
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 24 deletions.
52 changes: 28 additions & 24 deletions packages/vee-validate/src/Field.ts
@@ -1,8 +1,9 @@
import { h, defineComponent, toRef, SetupContext, resolveDynamicComponent, computed, watch } from 'vue';
import { getConfig } from './config';
import { useField } from './useField';
import { normalizeChildren, hasCheckedAttr, shouldHaveValueBinding } from './utils';
import { normalizeChildren, hasCheckedAttr, shouldHaveValueBinding, isPropPresent } from './utils';
import { toNumber } from '../../shared';
import { EMPTY_VALUE } from './symbols';

interface ValidationTriggersProps {
validateOnMount: boolean;
Expand Down Expand Up @@ -62,6 +63,7 @@ export const Field = defineComponent({
},
modelValue: {
type: null,
default: EMPTY_VALUE,
},
modelModifiers: {
type: null,
Expand Down Expand Up @@ -93,13 +95,7 @@ export const Field = defineComponent({
validateOnMount: props.validateOnMount,
bails: props.bails,
type: ctx.attrs.type as string,
// Gets the initial value either from `value` prop/attr or `v-model` binding (modelValue)
// For checkboxes and radio buttons it will always be the model value not the `value` attribute
initialValue: hasCheckedAttr(ctx.attrs.type)
? props.modelValue
: 'modelValue' in props
? props.modelValue
: ctx.attrs.value,
initialValue: resolveInitialValue(props, ctx),
// Only for checkboxes and radio buttons
valueProp: ctx.attrs.value,
uncheckedValue,
Expand All @@ -108,21 +104,19 @@ export const Field = defineComponent({
});

// If there is a v-model applied on the component we need to emit the `update:modelValue` whenever the value binding changes
const onChangeHandler =
'modelValue' in props
? function handleChangeWithModel(e: any) {
handleChange(e);
ctx.emit('update:modelValue', value.value);
}
: handleChange;

const onInputHandler =
'modelValue' in props
? function handleChangeWithModel(e: any) {
handleInput(e);
ctx.emit('update:modelValue', value.value);
}
: handleInput;
const onChangeHandler = isPropPresent(props, 'modelValue')
? function handleChangeWithModel(e: any) {
handleChange(e);
ctx.emit('update:modelValue', value.value);
}
: handleChange;

const onInputHandler = isPropPresent(props, 'modelValue')
? function handleChangeWithModel(e: any) {
handleInput(e);
ctx.emit('update:modelValue', value.value);
}
: handleInput;

const fieldProps = computed(() => {
const { validateOnInput, validateOnChange, validateOnBlur, validateOnModelUpdate } = resolveValidationTriggers(
Expand Down Expand Up @@ -161,7 +155,7 @@ export const Field = defineComponent({
return attrs;
});

if ('modelValue' in props) {
if (isPropPresent(props, 'modelValue')) {
const modelValue = toRef(props, 'modelValue');
watch(modelValue, newModelValue => {
if (newModelValue !== applyModifiers(value.value, props.modelModifiers)) {
Expand Down Expand Up @@ -237,3 +231,13 @@ function applyModifiers(value: unknown, modifiers: Record<string, boolean>) {

return value;
}

function resolveInitialValue(props: Record<string, unknown>, ctx: SetupContext<any>) {
// Gets the initial value either from `value` prop/attr or `v-model` binding (modelValue)
// For checkboxes and radio buttons it will always be the model value not the `value` attribute
if (!hasCheckedAttr(ctx.attrs.type)) {
return isPropPresent(props, 'modelValue') ? props.modelValue : ctx.attrs.value;
}

return isPropPresent(props, 'modelValue') ? props.modelValue : undefined;
}
2 changes: 2 additions & 0 deletions packages/vee-validate/src/symbols.ts
Expand Up @@ -12,3 +12,5 @@ export const FormInitialValuesSymbol: InjectionKey<ComputedRef<Record<string, un
);

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

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

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

return false;
}

export function isPropPresent(obj: Record<string, unknown>, prop: string) {
return prop in obj && obj[prop] !== EMPTY_VALUE;
}

0 comments on commit 0663539

Please sign in to comment.