Vue: Forcing child component to react to changes in its prop (which is a dictionary)











up vote
1
down vote

favorite












I am currently generating a table which lists problems encountered during the selected test using a component generated with this code:



<tr is="entry" v-for="problem in problems" :key="problem.id" v-bind:foo="problem"></tr>


Each problem corresponds to an item whose relevant information is contained within the problem dictionary and referenced in the first few columns of the table. Since the same item can have multiple problems, the same item can appear in multiple rows of the table. Now, each row features some buttons which allow you to modify the underlying item so as to fix the problems.



Whenever I modify one of those underlying items I need to modify it in all the rows, which i do by calling a function in the parent component, but modifying the data inside of the dictionary does not seem to trigger any of my watches or computes inside of the child component, which currently looks something like this:



Vue.component('entry', {
props: ['foo'],
data: function(){
//does some computations
return data
},
watch:{
foo: function(){
this.recompute_entry()
},
},
methods:{
//various methods, including:
recompute_entry: function(){
//updates the data according to changes brought to the entry
},
},
});


I have attempted to include a different prop which i could bind to an entry in a list in my parent component but, besides being pretty clunky, that didn't end up working either, which makes me think I might've gotten something wrong with my component.



Ultimately, I have relied on the fact that v-for iterates through my list in an orderly fashion, which combined with the fact that I generate no other children in my parent component means that a child component would have the same index in my component's children array as it would in my problems array. Therefore I can use this:



this.$children[problem_index].recompute_entry();


Which kind of feels hack-ish and unreliable, but actually works, for once. Is there no alternative safer method to recalculate my child components based on changes made to their props? I really feel there has to be.










share|improve this question


















  • 2




    Consider using [vuex|vuex.vuejs.org/] to store your data as your application's "state" and define mutations/getters to modify/access it. they have very nice examples in their github such as github.com/vuejs/vuex/tree/dev/examples/shopping-cart
    – mmbrian
    Nov 22 at 16:23















up vote
1
down vote

favorite












I am currently generating a table which lists problems encountered during the selected test using a component generated with this code:



<tr is="entry" v-for="problem in problems" :key="problem.id" v-bind:foo="problem"></tr>


Each problem corresponds to an item whose relevant information is contained within the problem dictionary and referenced in the first few columns of the table. Since the same item can have multiple problems, the same item can appear in multiple rows of the table. Now, each row features some buttons which allow you to modify the underlying item so as to fix the problems.



Whenever I modify one of those underlying items I need to modify it in all the rows, which i do by calling a function in the parent component, but modifying the data inside of the dictionary does not seem to trigger any of my watches or computes inside of the child component, which currently looks something like this:



Vue.component('entry', {
props: ['foo'],
data: function(){
//does some computations
return data
},
watch:{
foo: function(){
this.recompute_entry()
},
},
methods:{
//various methods, including:
recompute_entry: function(){
//updates the data according to changes brought to the entry
},
},
});


I have attempted to include a different prop which i could bind to an entry in a list in my parent component but, besides being pretty clunky, that didn't end up working either, which makes me think I might've gotten something wrong with my component.



Ultimately, I have relied on the fact that v-for iterates through my list in an orderly fashion, which combined with the fact that I generate no other children in my parent component means that a child component would have the same index in my component's children array as it would in my problems array. Therefore I can use this:



this.$children[problem_index].recompute_entry();


Which kind of feels hack-ish and unreliable, but actually works, for once. Is there no alternative safer method to recalculate my child components based on changes made to their props? I really feel there has to be.










share|improve this question


















  • 2




    Consider using [vuex|vuex.vuejs.org/] to store your data as your application's "state" and define mutations/getters to modify/access it. they have very nice examples in their github such as github.com/vuejs/vuex/tree/dev/examples/shopping-cart
    – mmbrian
    Nov 22 at 16:23













up vote
1
down vote

favorite









up vote
1
down vote

favorite











I am currently generating a table which lists problems encountered during the selected test using a component generated with this code:



<tr is="entry" v-for="problem in problems" :key="problem.id" v-bind:foo="problem"></tr>


Each problem corresponds to an item whose relevant information is contained within the problem dictionary and referenced in the first few columns of the table. Since the same item can have multiple problems, the same item can appear in multiple rows of the table. Now, each row features some buttons which allow you to modify the underlying item so as to fix the problems.



Whenever I modify one of those underlying items I need to modify it in all the rows, which i do by calling a function in the parent component, but modifying the data inside of the dictionary does not seem to trigger any of my watches or computes inside of the child component, which currently looks something like this:



Vue.component('entry', {
props: ['foo'],
data: function(){
//does some computations
return data
},
watch:{
foo: function(){
this.recompute_entry()
},
},
methods:{
//various methods, including:
recompute_entry: function(){
//updates the data according to changes brought to the entry
},
},
});


I have attempted to include a different prop which i could bind to an entry in a list in my parent component but, besides being pretty clunky, that didn't end up working either, which makes me think I might've gotten something wrong with my component.



Ultimately, I have relied on the fact that v-for iterates through my list in an orderly fashion, which combined with the fact that I generate no other children in my parent component means that a child component would have the same index in my component's children array as it would in my problems array. Therefore I can use this:



this.$children[problem_index].recompute_entry();


Which kind of feels hack-ish and unreliable, but actually works, for once. Is there no alternative safer method to recalculate my child components based on changes made to their props? I really feel there has to be.










share|improve this question













I am currently generating a table which lists problems encountered during the selected test using a component generated with this code:



<tr is="entry" v-for="problem in problems" :key="problem.id" v-bind:foo="problem"></tr>


Each problem corresponds to an item whose relevant information is contained within the problem dictionary and referenced in the first few columns of the table. Since the same item can have multiple problems, the same item can appear in multiple rows of the table. Now, each row features some buttons which allow you to modify the underlying item so as to fix the problems.



Whenever I modify one of those underlying items I need to modify it in all the rows, which i do by calling a function in the parent component, but modifying the data inside of the dictionary does not seem to trigger any of my watches or computes inside of the child component, which currently looks something like this:



Vue.component('entry', {
props: ['foo'],
data: function(){
//does some computations
return data
},
watch:{
foo: function(){
this.recompute_entry()
},
},
methods:{
//various methods, including:
recompute_entry: function(){
//updates the data according to changes brought to the entry
},
},
});


I have attempted to include a different prop which i could bind to an entry in a list in my parent component but, besides being pretty clunky, that didn't end up working either, which makes me think I might've gotten something wrong with my component.



Ultimately, I have relied on the fact that v-for iterates through my list in an orderly fashion, which combined with the fact that I generate no other children in my parent component means that a child component would have the same index in my component's children array as it would in my problems array. Therefore I can use this:



this.$children[problem_index].recompute_entry();


Which kind of feels hack-ish and unreliable, but actually works, for once. Is there no alternative safer method to recalculate my child components based on changes made to their props? I really feel there has to be.







vue.js vue-component parent-child vue-reactivity






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 22 at 16:06









2spriggan49

61




61








  • 2




    Consider using [vuex|vuex.vuejs.org/] to store your data as your application's "state" and define mutations/getters to modify/access it. they have very nice examples in their github such as github.com/vuejs/vuex/tree/dev/examples/shopping-cart
    – mmbrian
    Nov 22 at 16:23














  • 2




    Consider using [vuex|vuex.vuejs.org/] to store your data as your application's "state" and define mutations/getters to modify/access it. they have very nice examples in their github such as github.com/vuejs/vuex/tree/dev/examples/shopping-cart
    – mmbrian
    Nov 22 at 16:23








2




2




Consider using [vuex|vuex.vuejs.org/] to store your data as your application's "state" and define mutations/getters to modify/access it. they have very nice examples in their github such as github.com/vuejs/vuex/tree/dev/examples/shopping-cart
– mmbrian
Nov 22 at 16:23




Consider using [vuex|vuex.vuejs.org/] to store your data as your application's "state" and define mutations/getters to modify/access it. they have very nice examples in their github such as github.com/vuejs/vuex/tree/dev/examples/shopping-cart
– mmbrian
Nov 22 at 16:23












1 Answer
1






active

oldest

votes

















up vote
0
down vote













I probably would need to see the exact implementation but it sounds like you need to clone your dictionary to trigger the prop change, ie:



let newProblem = Object.assign({}, this.problem);
// change any nested property
newProblem.some.value = 1
// assign back the cloned and modified dictionary
this.problem = newProblem





share|improve this answer





















  • The exact implementation is around 500 lines of code, which is why I tried to avoid posting all of it. For what it's worth, I had already tried creating a new dictionary and assigning it to the problem, but I'm assuming the issue lies in the fact that the problem itself is inside of a list. If i reassign all of that I'd have to re-render the entire table, which would be too costly.
    – 2spriggan49
    Nov 23 at 10:20










  • Whoa, having 500 lines of code and also having all that data is a good sign that you should be breaking up that component into more components. Probably you can do it in a way that each child takes care of their own data with their own local state so that you don't need to re-render everything.
    – EderChrono
    Nov 23 at 17:28










  • That's including all my methods for filtering or sending data to the server, not just rendering and declaring my data. The gist of it absolutely boils down to the code I included in the original question really. Everything that's really missing is some filtering that is done wherein i use problems.push(element);` to add to my final list i build my entries out of, but I didn't consider that relevant.
    – 2spriggan49
    Nov 26 at 16:17













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53434709%2fvue-forcing-child-component-to-react-to-changes-in-its-prop-which-is-a-diction%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
0
down vote













I probably would need to see the exact implementation but it sounds like you need to clone your dictionary to trigger the prop change, ie:



let newProblem = Object.assign({}, this.problem);
// change any nested property
newProblem.some.value = 1
// assign back the cloned and modified dictionary
this.problem = newProblem





share|improve this answer





















  • The exact implementation is around 500 lines of code, which is why I tried to avoid posting all of it. For what it's worth, I had already tried creating a new dictionary and assigning it to the problem, but I'm assuming the issue lies in the fact that the problem itself is inside of a list. If i reassign all of that I'd have to re-render the entire table, which would be too costly.
    – 2spriggan49
    Nov 23 at 10:20










  • Whoa, having 500 lines of code and also having all that data is a good sign that you should be breaking up that component into more components. Probably you can do it in a way that each child takes care of their own data with their own local state so that you don't need to re-render everything.
    – EderChrono
    Nov 23 at 17:28










  • That's including all my methods for filtering or sending data to the server, not just rendering and declaring my data. The gist of it absolutely boils down to the code I included in the original question really. Everything that's really missing is some filtering that is done wherein i use problems.push(element);` to add to my final list i build my entries out of, but I didn't consider that relevant.
    – 2spriggan49
    Nov 26 at 16:17

















up vote
0
down vote













I probably would need to see the exact implementation but it sounds like you need to clone your dictionary to trigger the prop change, ie:



let newProblem = Object.assign({}, this.problem);
// change any nested property
newProblem.some.value = 1
// assign back the cloned and modified dictionary
this.problem = newProblem





share|improve this answer





















  • The exact implementation is around 500 lines of code, which is why I tried to avoid posting all of it. For what it's worth, I had already tried creating a new dictionary and assigning it to the problem, but I'm assuming the issue lies in the fact that the problem itself is inside of a list. If i reassign all of that I'd have to re-render the entire table, which would be too costly.
    – 2spriggan49
    Nov 23 at 10:20










  • Whoa, having 500 lines of code and also having all that data is a good sign that you should be breaking up that component into more components. Probably you can do it in a way that each child takes care of their own data with their own local state so that you don't need to re-render everything.
    – EderChrono
    Nov 23 at 17:28










  • That's including all my methods for filtering or sending data to the server, not just rendering and declaring my data. The gist of it absolutely boils down to the code I included in the original question really. Everything that's really missing is some filtering that is done wherein i use problems.push(element);` to add to my final list i build my entries out of, but I didn't consider that relevant.
    – 2spriggan49
    Nov 26 at 16:17















up vote
0
down vote










up vote
0
down vote









I probably would need to see the exact implementation but it sounds like you need to clone your dictionary to trigger the prop change, ie:



let newProblem = Object.assign({}, this.problem);
// change any nested property
newProblem.some.value = 1
// assign back the cloned and modified dictionary
this.problem = newProblem





share|improve this answer












I probably would need to see the exact implementation but it sounds like you need to clone your dictionary to trigger the prop change, ie:



let newProblem = Object.assign({}, this.problem);
// change any nested property
newProblem.some.value = 1
// assign back the cloned and modified dictionary
this.problem = newProblem






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 22 at 18:22









EderChrono

1847




1847












  • The exact implementation is around 500 lines of code, which is why I tried to avoid posting all of it. For what it's worth, I had already tried creating a new dictionary and assigning it to the problem, but I'm assuming the issue lies in the fact that the problem itself is inside of a list. If i reassign all of that I'd have to re-render the entire table, which would be too costly.
    – 2spriggan49
    Nov 23 at 10:20










  • Whoa, having 500 lines of code and also having all that data is a good sign that you should be breaking up that component into more components. Probably you can do it in a way that each child takes care of their own data with their own local state so that you don't need to re-render everything.
    – EderChrono
    Nov 23 at 17:28










  • That's including all my methods for filtering or sending data to the server, not just rendering and declaring my data. The gist of it absolutely boils down to the code I included in the original question really. Everything that's really missing is some filtering that is done wherein i use problems.push(element);` to add to my final list i build my entries out of, but I didn't consider that relevant.
    – 2spriggan49
    Nov 26 at 16:17




















  • The exact implementation is around 500 lines of code, which is why I tried to avoid posting all of it. For what it's worth, I had already tried creating a new dictionary and assigning it to the problem, but I'm assuming the issue lies in the fact that the problem itself is inside of a list. If i reassign all of that I'd have to re-render the entire table, which would be too costly.
    – 2spriggan49
    Nov 23 at 10:20










  • Whoa, having 500 lines of code and also having all that data is a good sign that you should be breaking up that component into more components. Probably you can do it in a way that each child takes care of their own data with their own local state so that you don't need to re-render everything.
    – EderChrono
    Nov 23 at 17:28










  • That's including all my methods for filtering or sending data to the server, not just rendering and declaring my data. The gist of it absolutely boils down to the code I included in the original question really. Everything that's really missing is some filtering that is done wherein i use problems.push(element);` to add to my final list i build my entries out of, but I didn't consider that relevant.
    – 2spriggan49
    Nov 26 at 16:17


















The exact implementation is around 500 lines of code, which is why I tried to avoid posting all of it. For what it's worth, I had already tried creating a new dictionary and assigning it to the problem, but I'm assuming the issue lies in the fact that the problem itself is inside of a list. If i reassign all of that I'd have to re-render the entire table, which would be too costly.
– 2spriggan49
Nov 23 at 10:20




The exact implementation is around 500 lines of code, which is why I tried to avoid posting all of it. For what it's worth, I had already tried creating a new dictionary and assigning it to the problem, but I'm assuming the issue lies in the fact that the problem itself is inside of a list. If i reassign all of that I'd have to re-render the entire table, which would be too costly.
– 2spriggan49
Nov 23 at 10:20












Whoa, having 500 lines of code and also having all that data is a good sign that you should be breaking up that component into more components. Probably you can do it in a way that each child takes care of their own data with their own local state so that you don't need to re-render everything.
– EderChrono
Nov 23 at 17:28




Whoa, having 500 lines of code and also having all that data is a good sign that you should be breaking up that component into more components. Probably you can do it in a way that each child takes care of their own data with their own local state so that you don't need to re-render everything.
– EderChrono
Nov 23 at 17:28












That's including all my methods for filtering or sending data to the server, not just rendering and declaring my data. The gist of it absolutely boils down to the code I included in the original question really. Everything that's really missing is some filtering that is done wherein i use problems.push(element);` to add to my final list i build my entries out of, but I didn't consider that relevant.
– 2spriggan49
Nov 26 at 16:17






That's including all my methods for filtering or sending data to the server, not just rendering and declaring my data. The gist of it absolutely boils down to the code I included in the original question really. Everything that's really missing is some filtering that is done wherein i use problems.push(element);` to add to my final list i build my entries out of, but I didn't consider that relevant.
– 2spriggan49
Nov 26 at 16:17




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53434709%2fvue-forcing-child-component-to-react-to-changes-in-its-prop-which-is-a-diction%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

What visual should I use to simply compare current year value vs last year in Power BI desktop

Alexandru Averescu

Trompette piccolo