Computed properties on Vuex state array objects












3















This question may also be applicable to Vue in general, but I am using Vuex for my project.



I have an array of objects in my store for which I would like to have a calculated property.



To simplify, assume my store is as follows:



const state = {
numbers = [
{num: 2, multiplier: 3},
{num: 5, multiplier: 10},
{num: 1, multiplier: 6}
]
};


Now, I want a calculated property on each object of the numbers array, such that the result is num * multiplier (eg. 2*3 = 6, 5*10 = 50)



One solution is to make a calculated property that returns the numbers array, plus the calculated field... eg:



const getterrs = {
num_list(state){
const list = state.numbers
list.map(n=>{
n.value=n.num*n.multiplier;
);
return list;
}
}


That works, but it has a couple issues:




  • The array returned cannot be bound with v-model on the non-computed
    fields


  • The entire array will be recalculated whenever any element in the
    array is changed... I only want to recalculate the individual element
    that changed.



Is that possible with Vue/Vuex?










share|improve this question



























    3















    This question may also be applicable to Vue in general, but I am using Vuex for my project.



    I have an array of objects in my store for which I would like to have a calculated property.



    To simplify, assume my store is as follows:



    const state = {
    numbers = [
    {num: 2, multiplier: 3},
    {num: 5, multiplier: 10},
    {num: 1, multiplier: 6}
    ]
    };


    Now, I want a calculated property on each object of the numbers array, such that the result is num * multiplier (eg. 2*3 = 6, 5*10 = 50)



    One solution is to make a calculated property that returns the numbers array, plus the calculated field... eg:



    const getterrs = {
    num_list(state){
    const list = state.numbers
    list.map(n=>{
    n.value=n.num*n.multiplier;
    );
    return list;
    }
    }


    That works, but it has a couple issues:




    • The array returned cannot be bound with v-model on the non-computed
      fields


    • The entire array will be recalculated whenever any element in the
      array is changed... I only want to recalculate the individual element
      that changed.



    Is that possible with Vue/Vuex?










    share|improve this question

























      3












      3








      3








      This question may also be applicable to Vue in general, but I am using Vuex for my project.



      I have an array of objects in my store for which I would like to have a calculated property.



      To simplify, assume my store is as follows:



      const state = {
      numbers = [
      {num: 2, multiplier: 3},
      {num: 5, multiplier: 10},
      {num: 1, multiplier: 6}
      ]
      };


      Now, I want a calculated property on each object of the numbers array, such that the result is num * multiplier (eg. 2*3 = 6, 5*10 = 50)



      One solution is to make a calculated property that returns the numbers array, plus the calculated field... eg:



      const getterrs = {
      num_list(state){
      const list = state.numbers
      list.map(n=>{
      n.value=n.num*n.multiplier;
      );
      return list;
      }
      }


      That works, but it has a couple issues:




      • The array returned cannot be bound with v-model on the non-computed
        fields


      • The entire array will be recalculated whenever any element in the
        array is changed... I only want to recalculate the individual element
        that changed.



      Is that possible with Vue/Vuex?










      share|improve this question














      This question may also be applicable to Vue in general, but I am using Vuex for my project.



      I have an array of objects in my store for which I would like to have a calculated property.



      To simplify, assume my store is as follows:



      const state = {
      numbers = [
      {num: 2, multiplier: 3},
      {num: 5, multiplier: 10},
      {num: 1, multiplier: 6}
      ]
      };


      Now, I want a calculated property on each object of the numbers array, such that the result is num * multiplier (eg. 2*3 = 6, 5*10 = 50)



      One solution is to make a calculated property that returns the numbers array, plus the calculated field... eg:



      const getterrs = {
      num_list(state){
      const list = state.numbers
      list.map(n=>{
      n.value=n.num*n.multiplier;
      );
      return list;
      }
      }


      That works, but it has a couple issues:




      • The array returned cannot be bound with v-model on the non-computed
        fields


      • The entire array will be recalculated whenever any element in the
        array is changed... I only want to recalculate the individual element
        that changed.



      Is that possible with Vue/Vuex?







      vue.js vuejs2 vuex






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 21 '18 at 0:20









      corycorycorycorycorycory

      297415




      297415
























          1 Answer
          1






          active

          oldest

          votes


















          0














          You could do any computing of your store data in the component it is being used in. I would have your getter simply return the numbers array:



          const getters = {
          num_list(state){
          return state.numbers;
          }
          }


          Then in your component you can access numbers with the getter and use it how you want. So if you want to display the original array you could get it like this:



          computed: {
          num_list() {
          return this.$store.getters.num_list
          }
          }


          and display it in your template like this:



          <p>Our first number is {{num_list[0].num}} and it's multiplier is {{num_list[0].num}}</p>


          If you want to have the multiplication calculated as well you can have another computed property:



          multiplied() {
          return this.num_list[0].num*this.num_list[0].multiplier
          }


          and echo it in the template with {{multiplied}}.



          Now it would make things a bit more flexible if you had a data element in your component that could be used as the index, or if you had a method instead of a computed property so you could pass a parameter. (You shouldn't pass parameters to computed property as I understand it). So your method of multiplied would be this:



          multipliedMethod(index) {
          return this.num_list[index].num*this.num_list[index].multiplier
          }


          Or if you want to show all the results you can iterate through your num_list with v-for and do any calculation on the fly:



          <div v-for="(num, index) in num_list" :key="index">
          <p>{{num.num*num.multiplier}}</p>
          </div>





          share|improve this answer
























          • That works fine for a single component, but one of the benefits of Vuex is managing a global state across multiple components. You would have to implement that computed property in every component you need to use it in. I was hoping for some kind of solution that doesn't violate the DRY principle :)

            – corycorycory
            Nov 21 '18 at 3:02











          • So you need an action and/or a mutation. An action is a global method, and can be called from anywhere. So the example method in my answer could be made into an action in your store. If you want to actually change your state then you need a mutation. If you want answers to your last two points you might need to include a use case in your question.

            – Andrew1325
            Nov 21 '18 at 4:02











          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',
          autoActivateHeartbeat: false,
          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%2f53403573%2fcomputed-properties-on-vuex-state-array-objects%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









          0














          You could do any computing of your store data in the component it is being used in. I would have your getter simply return the numbers array:



          const getters = {
          num_list(state){
          return state.numbers;
          }
          }


          Then in your component you can access numbers with the getter and use it how you want. So if you want to display the original array you could get it like this:



          computed: {
          num_list() {
          return this.$store.getters.num_list
          }
          }


          and display it in your template like this:



          <p>Our first number is {{num_list[0].num}} and it's multiplier is {{num_list[0].num}}</p>


          If you want to have the multiplication calculated as well you can have another computed property:



          multiplied() {
          return this.num_list[0].num*this.num_list[0].multiplier
          }


          and echo it in the template with {{multiplied}}.



          Now it would make things a bit more flexible if you had a data element in your component that could be used as the index, or if you had a method instead of a computed property so you could pass a parameter. (You shouldn't pass parameters to computed property as I understand it). So your method of multiplied would be this:



          multipliedMethod(index) {
          return this.num_list[index].num*this.num_list[index].multiplier
          }


          Or if you want to show all the results you can iterate through your num_list with v-for and do any calculation on the fly:



          <div v-for="(num, index) in num_list" :key="index">
          <p>{{num.num*num.multiplier}}</p>
          </div>





          share|improve this answer
























          • That works fine for a single component, but one of the benefits of Vuex is managing a global state across multiple components. You would have to implement that computed property in every component you need to use it in. I was hoping for some kind of solution that doesn't violate the DRY principle :)

            – corycorycory
            Nov 21 '18 at 3:02











          • So you need an action and/or a mutation. An action is a global method, and can be called from anywhere. So the example method in my answer could be made into an action in your store. If you want to actually change your state then you need a mutation. If you want answers to your last two points you might need to include a use case in your question.

            – Andrew1325
            Nov 21 '18 at 4:02
















          0














          You could do any computing of your store data in the component it is being used in. I would have your getter simply return the numbers array:



          const getters = {
          num_list(state){
          return state.numbers;
          }
          }


          Then in your component you can access numbers with the getter and use it how you want. So if you want to display the original array you could get it like this:



          computed: {
          num_list() {
          return this.$store.getters.num_list
          }
          }


          and display it in your template like this:



          <p>Our first number is {{num_list[0].num}} and it's multiplier is {{num_list[0].num}}</p>


          If you want to have the multiplication calculated as well you can have another computed property:



          multiplied() {
          return this.num_list[0].num*this.num_list[0].multiplier
          }


          and echo it in the template with {{multiplied}}.



          Now it would make things a bit more flexible if you had a data element in your component that could be used as the index, or if you had a method instead of a computed property so you could pass a parameter. (You shouldn't pass parameters to computed property as I understand it). So your method of multiplied would be this:



          multipliedMethod(index) {
          return this.num_list[index].num*this.num_list[index].multiplier
          }


          Or if you want to show all the results you can iterate through your num_list with v-for and do any calculation on the fly:



          <div v-for="(num, index) in num_list" :key="index">
          <p>{{num.num*num.multiplier}}</p>
          </div>





          share|improve this answer
























          • That works fine for a single component, but one of the benefits of Vuex is managing a global state across multiple components. You would have to implement that computed property in every component you need to use it in. I was hoping for some kind of solution that doesn't violate the DRY principle :)

            – corycorycory
            Nov 21 '18 at 3:02











          • So you need an action and/or a mutation. An action is a global method, and can be called from anywhere. So the example method in my answer could be made into an action in your store. If you want to actually change your state then you need a mutation. If you want answers to your last two points you might need to include a use case in your question.

            – Andrew1325
            Nov 21 '18 at 4:02














          0












          0








          0







          You could do any computing of your store data in the component it is being used in. I would have your getter simply return the numbers array:



          const getters = {
          num_list(state){
          return state.numbers;
          }
          }


          Then in your component you can access numbers with the getter and use it how you want. So if you want to display the original array you could get it like this:



          computed: {
          num_list() {
          return this.$store.getters.num_list
          }
          }


          and display it in your template like this:



          <p>Our first number is {{num_list[0].num}} and it's multiplier is {{num_list[0].num}}</p>


          If you want to have the multiplication calculated as well you can have another computed property:



          multiplied() {
          return this.num_list[0].num*this.num_list[0].multiplier
          }


          and echo it in the template with {{multiplied}}.



          Now it would make things a bit more flexible if you had a data element in your component that could be used as the index, or if you had a method instead of a computed property so you could pass a parameter. (You shouldn't pass parameters to computed property as I understand it). So your method of multiplied would be this:



          multipliedMethod(index) {
          return this.num_list[index].num*this.num_list[index].multiplier
          }


          Or if you want to show all the results you can iterate through your num_list with v-for and do any calculation on the fly:



          <div v-for="(num, index) in num_list" :key="index">
          <p>{{num.num*num.multiplier}}</p>
          </div>





          share|improve this answer













          You could do any computing of your store data in the component it is being used in. I would have your getter simply return the numbers array:



          const getters = {
          num_list(state){
          return state.numbers;
          }
          }


          Then in your component you can access numbers with the getter and use it how you want. So if you want to display the original array you could get it like this:



          computed: {
          num_list() {
          return this.$store.getters.num_list
          }
          }


          and display it in your template like this:



          <p>Our first number is {{num_list[0].num}} and it's multiplier is {{num_list[0].num}}</p>


          If you want to have the multiplication calculated as well you can have another computed property:



          multiplied() {
          return this.num_list[0].num*this.num_list[0].multiplier
          }


          and echo it in the template with {{multiplied}}.



          Now it would make things a bit more flexible if you had a data element in your component that could be used as the index, or if you had a method instead of a computed property so you could pass a parameter. (You shouldn't pass parameters to computed property as I understand it). So your method of multiplied would be this:



          multipliedMethod(index) {
          return this.num_list[index].num*this.num_list[index].multiplier
          }


          Or if you want to show all the results you can iterate through your num_list with v-for and do any calculation on the fly:



          <div v-for="(num, index) in num_list" :key="index">
          <p>{{num.num*num.multiplier}}</p>
          </div>






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 21 '18 at 2:50









          Andrew1325Andrew1325

          41829




          41829













          • That works fine for a single component, but one of the benefits of Vuex is managing a global state across multiple components. You would have to implement that computed property in every component you need to use it in. I was hoping for some kind of solution that doesn't violate the DRY principle :)

            – corycorycory
            Nov 21 '18 at 3:02











          • So you need an action and/or a mutation. An action is a global method, and can be called from anywhere. So the example method in my answer could be made into an action in your store. If you want to actually change your state then you need a mutation. If you want answers to your last two points you might need to include a use case in your question.

            – Andrew1325
            Nov 21 '18 at 4:02



















          • That works fine for a single component, but one of the benefits of Vuex is managing a global state across multiple components. You would have to implement that computed property in every component you need to use it in. I was hoping for some kind of solution that doesn't violate the DRY principle :)

            – corycorycory
            Nov 21 '18 at 3:02











          • So you need an action and/or a mutation. An action is a global method, and can be called from anywhere. So the example method in my answer could be made into an action in your store. If you want to actually change your state then you need a mutation. If you want answers to your last two points you might need to include a use case in your question.

            – Andrew1325
            Nov 21 '18 at 4:02

















          That works fine for a single component, but one of the benefits of Vuex is managing a global state across multiple components. You would have to implement that computed property in every component you need to use it in. I was hoping for some kind of solution that doesn't violate the DRY principle :)

          – corycorycory
          Nov 21 '18 at 3:02





          That works fine for a single component, but one of the benefits of Vuex is managing a global state across multiple components. You would have to implement that computed property in every component you need to use it in. I was hoping for some kind of solution that doesn't violate the DRY principle :)

          – corycorycory
          Nov 21 '18 at 3:02













          So you need an action and/or a mutation. An action is a global method, and can be called from anywhere. So the example method in my answer could be made into an action in your store. If you want to actually change your state then you need a mutation. If you want answers to your last two points you might need to include a use case in your question.

          – Andrew1325
          Nov 21 '18 at 4:02





          So you need an action and/or a mutation. An action is a global method, and can be called from anywhere. So the example method in my answer could be made into an action in your store. If you want to actually change your state then you need a mutation. If you want answers to your last two points you might need to include a use case in your question.

          – Andrew1325
          Nov 21 '18 at 4:02




















          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.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403573%2fcomputed-properties-on-vuex-state-array-objects%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







          這個網誌中的熱門文章

          Xamarin.form Move up view when keyboard appear

          Post-Redirect-Get with Spring WebFlux and Thymeleaf

          Anylogic : not able to use stopDelay()