In #app
, shoudld be parentObject
, not parentValue
.
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.
Vue.component('child', {
template: '#child',
//The child has a prop named 'value'. v-model will automatically bind to this prop
props: ['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">
<div>
<input type="text" v-bind:value="value.value1" v-on:input="$emit('input', {value1: $event.target.value, value2: value.value2})">
<input type="text" v-bind:value="value.value2" v-on:input="$emit('input', {value1: value.value1, value2: $event.target.value})">
</div>
</template>
About the <input>
s: you can bind each to a property of the parent's value
. 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:
$emit('input', {value1: value.value1, value2: $event.target.value})
With
$emit('input', Object.assign({}, value, {value2: $event.target.value}))
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:
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(propertyName, propertyValue) {
this.$emit('input', Object.assign({}, this.value, {[propertyName]: propertyValue}))
}
}
});
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">
<div>
<input type="text" v-bind:value="value.value1" v-on:input="updateValue('value1', $event.target.value)">
<input type="text" v-bind:value="value.value2" v-on:input="updateValue('value2', $event.target.value)">
</div>
</template>
The demo above, as you can see, already uses Object.assign()
, meaning it will handle an indefinite number of properties.