2
votes

I have async axios calls to my DB that I am dispatching with an action when the site loads. (I've tried dispatching in beforeEnter() on my Vue-router, beforeCreated(), and Created() on my Form.Vue)

I have a computed property return the info using a getter.

The problem I am experiencing is the data is getting there after the page has finished loading and returns Undefined - nothing renders on the page.

If I check my Vue DevTools, all the data is in the correct places in the State.

How can I get the data to finish loading before the page?

//ACTIONS

async loadInputs({ state, getters, commit, dispatch }) {    
 if (!state.loading) {
  commit('setLoading', true)

  const inputLists = axios.get('/companyInputLists')
  const inputs = axios.get('/companyInputs')

  commit('setLoading', false)
  commit('loadInputs' , [await inputLists, await inputs])

 }
},

set ({commit}, value) {
  commit('updateValue', value)
},

//MUTATORS

setLoading(state, value) {
  state.loading = value
},

 loadInputs(state, data){
  state.layout = {}
  state.data = {}
  data[0].data.map(list => {
    list['inputs'] = []
    state.layout[list.order] = list

    data[1].data.map(input => {
        if(input.list_id == list.id){
            state.layout[list.order].inputs.push(input)
            state.data[input.label] = ''
        }
     })
   })
 },

updateValue(state, value) {
  state.data[value.type] = value.value
},

//GETTERS

get(state) {
    console.log(state)
    return state
 },
}

//FORM.VUE

  <span>

    //LIST TEST and v-if test
    <div v-if="lists">
      {{lists}}
    </div>
    test
    {{ lists }}



<v-layout row wrap justify-center>

  <draggable class="dragArea layout row wrap justify-center" :options="{group:'lists'}">
    <v-flex v-for="list in lists" v-bind:key="list.index" :class="[list.label, flexBoxSize(list.size)]">

      <v-subheader v-text="list.label"></v-subheader>

      <draggable class="dragArea layout row wrap" :options="{group:'inputs'}">
        <v-flex v-for="item in list.inputs" v-bind:key="item.index" :class="[item.label, flexBoxSize(item.size)]">

          <textfield v-if="item.type_id == 1" formType="clientForm" :label="item.label" :required="item.required"></textfield>
          <email v-if="item.type_id == 2" formType="clientForm" :label="item.label"  :required="item.required"></email>
          <phone v-if="item.type_id == 3" formType="clientForm" :label="item.label"  :required="item.required"></phone>
          <calendar v-if="item.type_id == 4" formType="clientForm" :label="item.label"  :required="item.required"></calendar>
          <googleMap v-if="item.type_id == 5" formType="clientForm" :label="item.label"  :required="item.required"></googleMap>
          <autocomplete v-if="item.type_id == 6" formType="clientForm" :label="item.label"  :required="item.required"></autocomplete>


        </v-flex>
      </draggable>

    </v-flex>
  </draggable>


  <v-layout row wrap justify-center>
    <submitButton formType="clientForm" path="/clientForm" :references="this.$refs"></submitButton>
    <clearButton formType="clientForm" :references="this.$refs"></clearButton>
  </v-layout>

  </v-layout>
 </span>
</template>

<script>
export default {
  components: {
    draggable,
  },

  beforeCreate(){
    this.$store.dispatch('clientForm/loadInputs')
  },

  computed: {
    lists: {
      get() {
        return this.$store.getters['clientForm/get'].layout
      },
      set(value) {
        this.$store.commit('clientForm/updateInputList', value)
      }
    }
  },

Vuex Dev Tools Showing Data in State After Page Loads

2
What is the purpose of this line list['inputs'] = [] in loadInputs mutator? - user6748331
creates an array in the object to push inputs to ''''''''''''''' state.layout[list.order].inputs.push(input) - Dark9911
Ok. And can you add getters definition to answer? - user6748331
Okay, I added the getter - Dark9911
This linereturn this.$store.getters['clientForm/get'].layout really works? - user6748331

2 Answers

2
votes

I figured out the answer over the winter holidays last year and realized there never was a definitive conclusion posted here. After much trial and error and reading through documentation I came across the answer in the Vue.js documentation.

https://vuejs.org/v2/api/#Vue-set

Vue.set(target, key, value) Adds a property to a reactive object, ensuring the new property is also reactive, so triggers view updates. This must be used to add new properties to reactive objects, as Vue cannot detect normal property additions (e.g. this.myObject.newProperty = 'hi').

Using this function, I was able to load my data via an axios call and have Vue detect the changes and update the DOM.

Also you may want to take note of Vue.delete for removing data with reactivity.

0
votes

I think you can simplify your loadInputs action:

async loadInputs ({commit, state}) {
  if (!state.loading) {
    commit('setLoading', true)

    const inputLists = axios.get('/companyInputLists')
    const inputs = axios.get('/companyInputs')

    commit('setLoading', false)
    commit('loadInputs' , [await inputLists, await inputs])
   }
}

Component:

export default {
  components: {
    draggable,
  },
  computed: {
    lists: {
      get() {
        return this.$store.getters['clientForm/get'].layout
      },
      set(value) {
        this.$store.commit('clientForm/updateInputList', value)
      }
    }
  },
  created () {
    this.$store.dispatch('clientForm/loadInputs')
  },
}