Reputation: 360
I must be doing something wrong when trying to access the data of my child component.
I have two sets of data : targets and comparators. They can be updated with inputs by the user. Computed props update the data of the child component, and then I wanted to emit an event to the parent component thanks to the watchers I put on these two sets of data. However, these watchers seems to never be triggered..
This how the script of the child component looks like (remark, I only pasted two computed props):
<script>
export default {
name: "Targets",
props: ['mealPlan'],
data() {
return {
targets:{
weight: 0,
calories: 0,
carbs: 0,
proteins: 0,
fats: 0,
sugar: 0,
fibers: 0,
cholesterol: 0,
calcium: 0,
iron: 0,
sodium: 0,
potassium: 0,
cost: 0,
vitaminA: 0,
vitaminB6: 0,
vitaminB12: 0,
vitaminC: 0,
vitaminD: 0,
vitaminE: 0,
vitaminK: 0
},
comparators:{
weight: 0,
calories: 0,
carbs: 0,
proteins: 0,
fats: 0,
sugar: 0,
fibers: 0,
cholesterol: 0,
calcium: 0,
iron: 0,
sodium: 0,
potassium: 0,
cost: 0,
vitaminA: 0,
vitaminB6: 0,
vitaminB12: 0,
vitaminC: 0,
vitaminD: 0,
vitaminE: 0,
vitaminK: 0
}
}
},
computed:{
weightTarget:{
get:function(){
this.targets.weight = this.mealPlan.targetWeight;
return this.mealPlan.targetWeight;
},
set:function(newValue){
this.targets.weight = newValue
}
},
weightComparator:{
get:function(){
this.comparators.weight = this.mealPlan.comparatorWeight;
return this.mealPlan.comparatorWeight;
},
set:function(newValue){
this.comparators.weight = newValue
}
},
},
watch:{
targets:function(){
console.log(this.targets);
this.$emit('targetsUpdated', this.targets);
},
comparators:function(){
this.$emit('comparatorsUpdated', this.comparators);
}
}
}
</script>
The parent component receives the event like this :
<template>
<div>
<button @click="save" type="button" class="btn btn-success pull-left">Save</button>
<div>
<b-tab title="Targets">
<Targets
:meal-plan="mealPlan"
@targetsUpdated="targetsUpdated"
@comparatorsUpdated="comparatorsUpdated"
></Targets>
</b-tab>
</div>
</div>
</template>
<script>
import MealTable from "../components/MealTable";
import DayTable from "../components/DayTable";
import Targets from "./Targets";
import Specifications from "./Specifications";
export default {
name: "Edit",
components: {DayTable, MealTable,Targets,Specifications},
data(){
return{
mealPlan: {},
currentDay: '1',
targets:{},
comparators:{},
}
},
computed: {
methods:{
targetsUpdated(newTargets){
this.targets = {
weight: newTargets.targetWeight,
calories: newTargets.targetCalories,
carbs: newTargets.targetCarbs,
proteins: newTargets.targetProteins,
fats: newTargets.targetFats,
sugar: newTargets.targetSugar,
fibers: newTargets.targetFibers,
cholesterol: newTargets.targetCholesterol,
calcium: newTargets.targetCalcium,
iron: newTargets.targetIron,
sodium: newTargets.targetSodium,
potassium: newTargets.targetPotassium,
cost: newTargets.targetCost,
vitaminA: newTargets.targetVitaminA,
vitaminB6: newTargets.targetVitaminB6,
vitaminB12: newTargets.targetVitaminB12,
vitaminC: newTargets.targetVitaminC,
vitaminD: newTargets.targetVitaminD,
vitaminE: newTargets.targetVitaminE,
vitaminK: newTargets.targetVitaminK
}
},
comparatorsUpdated(newComparators){
this.comparators = {
weight: newComparators.comparatorWeight,
calories: newComparators.comparatorCalories,
carbs: newComparators.comparatorCarbs,
proteins: newComparators.comparatorProteins,
fats: newComparators.comparatorFats,
sugar: newComparators.comparatorSugar,
fibers: newComparators.comparatorFibers,
cholesterol: newComparators.comparatorCholesterol,
calcium: newComparators.comparatorCalcium,
iron: newComparators.comparatorIron,
sodium: newComparators.comparatorSodium,
potassium: newComparators.comparatorPotassium,
cost: newComparators.comparatorCost,
vitaminA: newComparators.comparatorVitaminA,
vitaminB6: newComparators.comparatorVitaminB6,
vitaminB12: newComparators.comparatorVitaminB12,
vitaminC: newComparators.comparatorVitaminC,
vitaminD: newComparators.comparatorVitaminD,
vitaminE: newComparators.comparatorVitaminE,
vitaminK: newComparators.comparatorVitaminK
}
}
}
}
</script>
To sum up, I do not understand while the watcher on targets or comparators is not triggered, thanks for the help guys !
Upvotes: 0
Views: 44
Reputation: 3563
In addition to the usage of watchers one can simply add the same logic to the setters:
e.g:
weightComparator:{
get:function(){
this.comparators.weight = this.mealPlan.comparatorWeight;
return this.mealPlan.comparatorWeight;
},
set:function(newValue){
let oldValue = this.comparators.weight
this.$emit('change:comparators:weight', newValue, oldValue)
let oldComparators = Object.assign({}, this.comparators) // shallow copy
this.comparators.weight = newValue
this.$emit('changed:comparators', Object.assign({}, this.comparators), oldComparators)
}
},
Upvotes: 0
Reputation: 3972
So when you watch an array or an object, Vue has no idea that you've changed what's inside that data. You have to tell Vue that you want it to inspect inside of the data when watching for changes.
You can do this by setting deep to true on your watcher and rearranging the handler function.
watch: {
targets: {
// This will let Vue know to look inside the object
deep: true,
// We have to move our method to a handler field
handler()
this.$emit('targetsUpdated', this.targets);
}
},
comparators: {
// This will let Vue know to look inside the object
deep: true,
// We have to move our method to a handler field
handler()
this.$emit('comparatorsUpdated', this.comparators);
}
}
}
Upvotes: 2