Vue doenst update modelValue inside watch

69 Views Asked by At

Emitting update:modelValue event inside $watch doesnt update modelValue if I dont pass modelValue by props. How I can make sure modelValue is updated without passing modelValue by props?

MyComponent:

export default defineComponent(
{
    template: '<div>{{modelValue}}</div>',
    props: 
    {
        modelValue: {type: Date},
        stringValue: {type: String},
    },
    emits: ['update:modelValue', 'update:stringValue'],
    mounted()
    {
        this.$watch(() => this.stringValue, (n, o) => 
        {
            let value = n == null ? null : moment(n, Format.NewMomentDate).toDate();
            
            this.$emit('update:modelValue', value);
        }, {immediate: true});
    }
}

Usage:

<MyComponent v-model:string-value="ValidUntil">
</MyComponent>
1

There are 1 best solutions below

2
On

I think this comes from a misunderstanding of how props work.

First of: props are (supposed to be treated as) read-only.

Vue doesn't have a two-way binding like AngularJS had. What it has is two one-way bindings: props and events.

v-models are just a nicer syntax to work with that: it both binds a prop and and event listener.

The traditional flow is like this:

  1. Bind the reactive data to modelValue
  2. Bind the updater on update:modelValue
  3. Trigger update:modelValue
  4. The updater gets called and changes your reactive data
  5. The prop value of modelValue gets changed and the component re-renders the changed parts

Here update:modelValue is triggered but since there's no listener for it, nothing will happen. Therefore, modelValue still has its default value: undefined.