DEV Community

Using v-model with objects in Vue3

Blind Kai on November 30, 2021

Motivation When I was using Vue2 along with vue-class-component and vue-property-decorator it was easy to synchronize v-models between c...
Collapse
 
hansonfang profile image
hansonfang

In the 'get' of computed, is the reactivity deeply? I used this way back in vue2, turn out I had to use watch with deep option to make it work.

Collapse
 
blindkai profile image
Blind Kai • Edited

It depends. If you define new properties - you probably want to use Vue.set or $vm.set. Vue 2 works using patching mechanism that modify object fields to use getters and setters, and it's done during initialization. Any other field won't be reactive if you don't set it with options written above.

So it all depends on if you're creating completely new objects or adjust some properties you probably want to use Vue.set or Object.assign({}, oldObject, ...) etc.

You could find more descriptive information with examples in the official documentation.

Collapse
 
hansonfang profile image
hansonfang

That's make sense, thanks

Collapse
 
lucasctd profile image
Lucas Reis

You saved my day, I was struggling a lot with this XD Everytime I emitted the updated event I was getting an undefined object error, the default option saved me =D

In my case I am only using the emit event inside a watch (cuz I have a custom condition to update other property of the model). Vue seems to already send the emit event by default so no need to do it manually everytime.

Collapse
 
branquito profile image
Branchito de Munze

Actually that setter inside computed theModel will never run, which you can easily prove by commenting out that emit statement inside of it, because theModel.foo on input will be changed by mutating that model and not re-assigning over it

Collapse
 
zeeshan_khan_a777369d4ece profile image
Zeeshan Khan

Hey, so if the setter function never runs then how come the value in the parent component gets updated? And if I want to call a function in the setter how do I do that?

Collapse
 
lucasctd profile image
Lucas Reis

Thank you so much buddy!

Collapse
 
blindkai profile image
Blind Kai

I'm happy to be helpful!

Collapse
 
pleasefilloutthisfield profile image
please-fill-out-this-field

What if I need to validate the value first or make adjustments before emit()ing?

Collapse
 
blindkai profile image
Blind Kai

You could extend the setter.
For example:

const theModel = computed({
  get: () => props.modelValue,
  set: (value) => {
    const isValid = someValidation(value); // Put the logic in setter
    if (isValid) emit('update:modelValue', value);
  },
});
Enter fullscreen mode Exit fullscreen mode
Collapse
 
zeeshan_khan_a777369d4ece profile image
Zeeshan Khan

The setter function does not run as the theModel key is bind to the input field not the theModel.

Collapse
 
neopixel profile image
NeoPixel.sk

After couple of hours, I found your solution and it works flawlessly! Thank you!

Collapse
 
blindkai profile image
Blind Kai

I'm glad that the article was helpful!