0

I am using Vue to build a kind of form builder with dynamic meta elements. See here:

<div v-for="item in getFieldType(selectedElement.type).meta"
     :key="item.id">
  <div class="form-group">
    <label>{{ item.label }}</label>
    <TextField
      :value="selectedElement.meta[item.id]"
      :label="item.label"
      :name="item.label"
      type="text"/>
  </div>
</div>

This is simply presented the definition of the field types + the loading of the fields from the API:

mounted()
  {
    this.file = await this.$store.dispatch('files/fetch', this.$route.params.id);
    // [...]
    this.selectedElement = this.file.fields[1].rawFields; // Simplified
  },

  data() {
    return {
      fieldTypes: [
        {
          type: 'singleline-text',
          label: 'Singleline Textfields',
          config: {
            minwidth: 50,
            name: true,
          },
          meta: [
            {
              type: 'text',
              label: 'Prefilled Value',
              hint: 'This value will be prefilled',
              id: 'prefilled'
            }
          ]
        }
      ]
    };
  }

So basically this is beeing used from VueX: this.file.fields[1].rawFields

Unforunately when I try to edit the TextField, I am getting following error:

[vuex] do not mutate vuex store state outside mutation handlers.

I researched and found this in docu: https://vuex.vuejs.org/guide/forms.html but it does not help as my approach is more dynamic. I have to find a way to "unbind" the rawFields from the vueX state as I wont need it there anymore later. I don't want to set strict to false. Is there any elegant way to solve this issue?

I also found this which describes how to handle it keeping it in Vue state: Vuex - Do not mutate vuex store state outside mutation handlers

But in my case it will make more sense to just unbind it instead of writing more getters, setters, blur/focus listeners etc.

Maxi
  • 415
  • 4
  • 24

2 Answers2

2

You can trie to add lodash and use this function https://lodash.com/docs/4.17.15#cloneDeep

In mounted do like this

this.selectedElement = _.cloneDeep(this.file.fields[1].rawFields); // Simplified
FightInGlory
  • 448
  • 2
  • 6
  • Yes that worked thanks. Imported it with `npm i --save lodash.clonedeep` and added `import lodash from 'lodash';` – Maxi Jun 29 '20 at 19:53
  • One more hint: This will return an Object, even if it was an Array before. This helps to get it back to an Array: https://stackoverflow.com/questions/38824349/how-to-convert-an-object-to-an-array-of-key-value-pairs-in-javascript – Maxi Jun 29 '20 at 20:00
0

You can do this without an external dependency:

const clone = JSON.parse(JSON.stringify(obj))
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129