Reputation: 711
I have the below child component. The props are updated from an input selector in the parent. Why does level: this.globalForm.level
not update the child's level
Parent:
<template>
<div>
<div class="form-container">
<select class="form-control" v-model="level">
<option v-for="level in options" v-bind:key="level">{{ level }}</option>
</select>
<button @click="submit()">Create</button>
</div>
<child v-bind:globalForm="globalForm"/>
</div>
</template>
<script>
inputFiled;
export default {
data() {
return {
level: "",
globalForm: {
level: ""
},
options: ["level1", "level2", "level3"]
};
},
components: {
child
},
methods: {
submit() {
this.globalForm.level = this.level;
}
},
watch: {
level() {
this.globalForm.level = this.level;
}
}
};
</script>
Child:
<template>
<div class="form-container">
<option v-for="level in options" v-bind:key="level">{{ level }}</option>
</div>
</template>
<script>
export default {
props: { globalForm: Object },
data() {
return {
options: ["level1","level2","level3",],
level: this.globalForm.level //this does not update the child's level component
};
}
};
</script>
Upvotes: 0
Views: 1315
Reputation: 2778
TLDR
level
should be a computed property on the child so that you can detect changes in the prop. You are setting level
in the data
function, so updates to the prop never make it to level
.
Below you'll find a minimal example on what I think you want to achieve.
Vue.config.productionTip = false;
Vue.component('parent', {
template: `
<div class="parent">
<b>PARENT</b>
<div class="form-container">
<select class="form-control" v-model="level">
<option v-for="level in options" v-bind:key="level">{{ level }}</option>
</select>
<button @click="submit()">Create</button>
</div>
<child v-bind:globalForm="globalForm"/>
</div>
`,
data: () => ({
level: "",
globalForm: {
level: ""
},
options: ["level1", "level2", "level3"]
}),
methods: {
submit() {
this.globalForm.level = this.level;
}
}
});
Vue.component('child', {
template: `
<div class="form-container child">
<p><b>Child</b></p>
Level: {{ level }}
</div>
`,
props: {
globalForm: Object
},
computed: {
level() {
return this.globalForm.level;
}
}
});
new Vue({
el: "#app"
})
.parent {
background-color: darkgray;
padding: .5em;
border: solid 1px black;
}
.child {
background-color: lightgray;
padding: .5em;
border: solid 1px black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<parent></parent>
</div>
More Detailed explanation
There are couple of errors on your code that I'll go through.
In your child component
When initializing your component, this
is not available inside the data
function, so this.globalForm
will be undefined. An error is thrown in the console when reproducing it.
data() {
return {
options: ["level1","level2","level3",], // this looks like duplicated code from the parent
level: this.globalForm.level // throws error
};
}
To fix that error, you can get the vm
context from the parameters of data
But this is not the solution for your question.
data(vm) { // note vm
return {
level: vm.globalForm.level // note vm
};
}
The real problem is that level: this.globalForm.level
runs only once, in your component initialization, so level is undefined
. When the globalForm
prop changes, level
has already been initialized and it will not change (data returns a new object so the reference to the prop is lost).
You want convert level
to be a computed property so that changes to the prop can be detected and the inner value returned. See code snippet above.
Upvotes: 1