Vue .sync only works with v-model, but gives mutation error

Tags: , , , ,



// NOTE: Issue was due to VueFormulate’s FormulaInput (custom input).

Check the code sandbox for 3 working examples of .sync



Usecase

My app is injecting multiple dynamic components into a view which then binds multiple inputs within each component to data in the parent.

Since v-model only works on a single value, I’ve found that .sync (added again after Vue 2.3) is the only way to two-way bind multiple inputs in each child component to my parent’s data.

The Problem

I’ve followed the exact syntax in the Vue docs and many tutorials, but when I use :value="value in my child component it inputs undefined in my data with no errors in console.

If I use v-model, it works as expected, however produces a no-mutate-props error in the console for every single keystroke I press.

Expected Result

I expect two-way binding to work without producing any errors of no-mutate-props in the console.

I think I need some kind of watcher to check a value that references my prop, but that seems a bit messy, and I’d have to implement it for like 30 components… I’d would prefer something cleaner if possible.

Code Sandbox Example of issue

In Child

// input1
<input
  type="text"
  :value="value" <----- this will work if I make it a v-model, but produces mutation error in console
  @input="$emit('update:value', value)"
/>

// input2
<input
  type="text"
  :value2="value2" <----- again, will work with v-model only
  @input="$emit('update:value2', value2)"
/>

props: {
  value: {
    type: String
  },
  value2: {
    type: String
  }
}

In Parent

<component
  :is="step.component"
  :value.sync="step.value"
  :value2.sync="step.value2"
  :value3.sync="step.value3"
/>

Answer

The reason value didn’t work is only because you are emitting the same unchanged value which is passed down. Without v-model, nothing changes value, so there was nothing new to emit back up.

Change that input to:

<input
  :value="value"
  @input="$emit('update:value', $event.target.value)"
  type="text"
  step="1"
  placeholder="Child Input1 (value)"
/>

This way, when the input event happens, you emit a new value from the input box.



Source: stackoverflow