@Model does not work with "required: false"
philippmaurer opened this issue · 4 comments
Current behavior
Add a @Model
to a field and provide the property option required: false
to it.
@Model({type: String, required: false, default:'Hello World'})
fieldName!: string;
If you do not provide a property modelValue
in this szenario, or if you provide it with v-bind
rather than v-model
(:modelValue="someVar"
), changes to the field fieldName
inside the component will have no effect and not change any state. No errors or warnings are shown in any logs.
In the same szenario, but with the configuration required: true
, Vue shows warning logs for a missing property in the browser logs.
Expected behavior
-
Option 1
It should not be possible to configure a field annotated with@Model
asrequired: false
. -
Option 2
A property annotated with@Model
andrequired: false
should still function like a normal property in the component, if the property is not provided by the parent. -
optional / debatable
@Model
should also work if the parent component provides the property usingv-bind
rather thanv-model
.
Technical explanation
@Model
is mapped to a computed property that in it's set
method only emits a update:modelValue
event. If no property is provided from the parent, the event is not listened to and the parent does not adjust the value of the property. Therefore the property does not change in the current component.
Workaround
Use @Prop
instead, create an internal data field that is in sync with the property and handle the update:modelValue
emits manually.
@Prop({type: String, required: false, default:'Hello World'})
modelValue!: string;
fieldName!: string;
mounted() {
this.alignFieldNameWithModelValue();
}
@Watch('modelValue')
alignFieldNameWithModelValue() {
if (this.fieldName !== this.modelValue) {
this.fieldName = modelValue;
}
}
@Watch('fieldName')
emitFieldNameChange() {
if (this.fieldName !== this.modelValue) {
this.$emit('update:modelValue', this.fieldName);
}
}
I just want to mention that i am willing to contribute in this redards, if a MR is wanted.
@philippmaurer pull requests are always welcome!
@ruojianll any thoughts about the request/functionality here?
In my opinion, v-model
is a syntactic sugar to combine prop and event. So it should be compatible with props option. If required is false, it is optional. If default is set, it should have a default value.
v-model
could downgrade to a normal prop if required false or default is set.
changes to the field fieldName inside the component will have no effect and not change any state. No errors or warnings are shown in any logs.
We shouldn't change props in current component, props and event are both an one-way dataflow, so we should use event to trigger changes in parent component.
v-model="foo"
will be compiled in to :modelValue="foo"
and @update:modelValue="(e)=>foo.value=e"
by vue template compiler.
Because defineModel declares a prop, you can therefore declare the underlying prop's options by passing it to defineModel...
If you have a default value for defineModel prop and you don't provide any value for this prop from the parent component, it can cause a de-synchronization between parent and child components.
https://vuejs.org/guide/components/v-model.html#component-v-model