I am trying to create a component that accepts an object as prop and can modify different properties of that object and return the value to the parent, using either sync or emit events. The example won't work, but it's simply to demonstrate what I'm trying to achieve.
Here's a snippet of what I'm trying to achieve :
Vue.component('child', {
template: '#child',
//The child has a prop named 'value'. v-model will automatically bind to this prop
props: ['value'],
methods: {
updateValue: function (value) {
//Not sure if both fields should call the same updateValue method that returns the complete object, or if they should be separate
this.$emit('input', value);
}
}
});
new Vue({
el: '#app',
data: {
parentObject: {value1: "1st Value", value2: "2nd value"}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<p>Parent value: {{parentObject}}</p>
<child v-model="parentObject"></child>
</div>
<template id="child">
<input type="text" v-bind:value.value1="value" v-on:input="updateValue($event.target.value)">
<input type="text" v-bind:value.value2="value" v-on:input="updateValue($event.target.value)">
</template>
In
#app
, shoudld beparentObject
, notparentValue
.In child, you had two
inpyt
, but you must have a single root element. In the example below I created a<div>
root element for the component.To update the parent, emit the events. This approach does not modify the parent's property in the child, so there's no breaking of the One-Way data flow.
About the
<input>
s: you can bind each to a property of the parent'svalue
. Then, when edited, emit an event modifying just that property (v-on:input="$emit('input', {value1: $event.target.value, value2: value.value2})
) and keeping the other's value. The parent updates in consequence.If you have many properties, you can replace in the second
input
, for example:With
Using a method instead of emitting directly from the template
I kept the previous demo because it is more direct and simpler to understand (less changes from your original code), but a more compact approach would be to use a method (e.g.
updateValue
) and reuse it in the template:The demo above, as you can see, already uses
Object.assign()
, meaning it will handle an indefinite number of properties.You shouldn't modify the object being passed in as a prop. Instead, you should create a new data property in the child component and initialize it with a copy of the prop object.
Then, I would just use a
v-model
for each of the inputs in the child component and add a deep watcher to the internal value which would emit anupdate
whenever the internal value changes.I made a shallow copy of the prop in my example (
{...this.value}
), because the object doesn't have any nested properties. If that wasn't the case, you might need to do a deep copy (JSON.parse(JSON.stringify(this.value))
).It is not possible. There is a closed issue asking for it. This is the shortest method I found:
Script
Template
https://jsfiddle.net/5k4ptmqg/475/