11import { h , defineComponent , toRef , SetupContext , resolveDynamicComponent , computed , watch } from 'vue' ;
22import { getConfig } from './config' ;
33import { useField } from './useField' ;
4- import { normalizeChildren , hasCheckedAttr , shouldHaveValueBinding } from './utils' ;
4+ import { normalizeChildren , hasCheckedAttr , shouldHaveValueBinding , isPropPresent } from './utils' ;
55import { toNumber } from '../../shared' ;
6+ import { EMPTY_VALUE } from './symbols' ;
67
78interface ValidationTriggersProps {
89 validateOnMount : boolean ;
@@ -62,6 +63,7 @@ export const Field = defineComponent({
6263 } ,
6364 modelValue : {
6465 type : null ,
66+ default : EMPTY_VALUE ,
6567 } ,
6668 modelModifiers : {
6769 type : null ,
@@ -93,13 +95,7 @@ export const Field = defineComponent({
9395 validateOnMount : props . validateOnMount ,
9496 bails : props . bails ,
9597 type : ctx . attrs . type as string ,
96- // Gets the initial value either from `value` prop/attr or `v-model` binding (modelValue)
97- // For checkboxes and radio buttons it will always be the model value not the `value` attribute
98- initialValue : hasCheckedAttr ( ctx . attrs . type )
99- ? props . modelValue
100- : 'modelValue' in props
101- ? props . modelValue
102- : ctx . attrs . value ,
98+ initialValue : resolveInitialValue ( props , ctx ) ,
10399 // Only for checkboxes and radio buttons
104100 valueProp : ctx . attrs . value ,
105101 uncheckedValue,
@@ -108,21 +104,19 @@ export const Field = defineComponent({
108104 } ) ;
109105
110106 // If there is a v-model applied on the component we need to emit the `update:modelValue` whenever the value binding changes
111- const onChangeHandler =
112- 'modelValue' in props
113- ? function handleChangeWithModel ( e : any ) {
114- handleChange ( e ) ;
115- ctx . emit ( 'update:modelValue' , value . value ) ;
116- }
117- : handleChange ;
118-
119- const onInputHandler =
120- 'modelValue' in props
121- ? function handleChangeWithModel ( e : any ) {
122- handleInput ( e ) ;
123- ctx . emit ( 'update:modelValue' , value . value ) ;
124- }
125- : handleInput ;
107+ const onChangeHandler = isPropPresent ( props , 'modelValue' )
108+ ? function handleChangeWithModel ( e : any ) {
109+ handleChange ( e ) ;
110+ ctx . emit ( 'update:modelValue' , value . value ) ;
111+ }
112+ : handleChange ;
113+
114+ const onInputHandler = isPropPresent ( props , 'modelValue' )
115+ ? function handleChangeWithModel ( e : any ) {
116+ handleInput ( e ) ;
117+ ctx . emit ( 'update:modelValue' , value . value ) ;
118+ }
119+ : handleInput ;
126120
127121 const fieldProps = computed ( ( ) => {
128122 const { validateOnInput, validateOnChange, validateOnBlur, validateOnModelUpdate } = resolveValidationTriggers (
@@ -161,7 +155,7 @@ export const Field = defineComponent({
161155 return attrs ;
162156 } ) ;
163157
164- if ( 'modelValue' in props ) {
158+ if ( isPropPresent ( props , 'modelValue' ) ) {
165159 const modelValue = toRef ( props , 'modelValue' ) ;
166160 watch ( modelValue , newModelValue => {
167161 if ( newModelValue !== applyModifiers ( value . value , props . modelModifiers ) ) {
@@ -237,3 +231,13 @@ function applyModifiers(value: unknown, modifiers: Record<string, boolean>) {
237231
238232 return value ;
239233}
234+
235+ function resolveInitialValue ( props : Record < string , unknown > , ctx : SetupContext < any > ) {
236+ // Gets the initial value either from `value` prop/attr or `v-model` binding (modelValue)
237+ // For checkboxes and radio buttons it will always be the model value not the `value` attribute
238+ if ( ! hasCheckedAttr ( ctx . attrs . type ) ) {
239+ return isPropPresent ( props , 'modelValue' ) ? props . modelValue : ctx . attrs . value ;
240+ }
241+
242+ return isPropPresent ( props , 'modelValue' ) ? props . modelValue : undefined ;
243+ }
0 commit comments