Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly deal with editable complex object (nested) with vuex?

Tags:

vuejs2

vuex

Vuex is really nice to display complex data, and do complex mutations (like adding a node to a tree with repercussions all across the store etc.), However, to me, it feels like a pain in the ass dealing with "simple" mutations on complex objects.

One use case I'm facing is (quite) simple : I have a component that displays a list object (with nested properties and arrays). Each properties are editable. Each object is displayed with a subcomponent. (and I need to use v-model on leaf properties)

The other use case is a modal dialog that is opened using a component's method, that will permit to edit some properties / nested properties of the object (and also, I needs to use v-model on leaf properties)

Currently, This is what I do : In the components that display / edit an object, I put in the component's data a "skeleton" of the objects that could be edited (an object with all nested properties present, but all leaf set to null). Then, when the modal open, or the component should display / make editable an object, I simply deep copy the object (using a recursive function) to the data one, and I watch the data one with deep option to true, and commit on each change.

This feels a bit wrong, and needs quite an effort to make it work.

I like the mutation traceability system, and what I would like is to commit my whole object each time a modification is done on a nested property. That would be really great if it was possible without writing such an amount of code (I'm wondering if it wouldn't be worthy to simply give up vuex for a simple global Vue Componnent store... and trade off the nice mutation system for simple code)

So is there a "standard" way or a "recommended way" ...Or simply a "smart" way to do it without requiring such an effort ?

Example of store state :

state = {
  foo : [
    bar : {
      users : [
        {
          name : '',
          adddr : '',
          needs : ['a', 'b', 'c'],
          baz : [
            {
              k1 : v1,
              k2 : v2,
              k3 : [1,2,3,4,5],
            },
            //...
          ]
        },
        //...
      ]
    }
  ]
}

...And I would like to commit each time whole user.

like image 511
hl037_ Avatar asked Aug 03 '18 12:08

hl037_


1 Answers

I suggest to use on this way:

  1. The component contains the full path of the property to be updated (this will be fired)
  2. In vuex use lodash or another similar tool to set the property using the full path.

Component

<template>
        <input v-on:change="update(‘object.nested.more.nested.attribute’, $event)" v-text:value="object.nested.mote.nested.attribute"></span>
</template>


<script>
 export default  {
  methods: {
    update: function (property, value) {
      this.$store.dispatch(UPDATE_COMPLEX_OBJECT, {property, value})
    }
  }
}
</script>

VUEX

import _ from 'lodash'

export default {
  namespaced: true,
  state: {
   myObject: {}
  },
  mutations: {
    [UPDATE_COMPLEX_OBJECT] (state, data) {
      _.set(state.myObject, data.property, data.value)
    }
  },
  actions: {
    [UPDATE_COMPLEX_OBJECT]: ({commit}, data) => {
      commit(UPDATE_COMPLEX_OBJECT, data)
    }
  }

}

Let me know if something is not clear and hope this help you. Thanks!

like image 88
Emiliano Barboza Avatar answered Oct 23 '22 10:10

Emiliano Barboza