1
votes

I'm using vuex to manage the state in my application and doing one way binding with my form.

<script>
  import { mapGetters } from 'vuex'
  import store from 'vuex-store'

  import DataWidget from '../../../../uiComponents/widget'
  export default {
    data () {
      return {
        isEdit: false,
        msg: {
          id: 0,
          content: '',
          isEnabled: false
        }
      }
    },
    components: {
      DataWidget
    },
    computed: mapGetters({
      messageId: 'messageId',
      messageContent: 'messageContent',
      isMessageEnabled: 'isMessageEnabled',
      isMessageValid: 'isMessageValid'
    }),
    methods: {
      onSave () {
        store.dispatch('saveMessage', this.msg, { root: true })
        if (this.isMessageValid) {
          this.isEdit = !this.isEdit
        }
      }
    },
    created () {
      this.msg.id = this.messageId
      this.msg.content = this.messageContent
      this.msg.isEnabled = this.isMessageEnabled
    }

  }
</script>

<b-form-textarea id="content" v-model="msg.content" :rows="3" required aria-required="true" maxlength="250"></b-form-textarea>

On load, the values on created() are not binded until I perform an action on the page or refresh the page.

I have tried mounted () hooked same thing.

My Vuex store (Message Module) looks like this:

const state = {
  messageId: 0,
  messageContent: '',
  isMessageEnabled: false,
  isMessageValid: true
}

const getters = {
  messageId: state => state.messageId,
  messageContent: state => state.messageContent,
  isMessageEnabled: state => state.isMessageEnabled,
  isMessageValid: state => state.isMessageValid
}

const actions = {
  getMessage ({commit, rootGetters}) {
    api.fetch('api/Preference/Message', rootGetters.token)
    .then((data) => {
      commit(types.MESSAGE_LOAD, data)
    })
  }
}

const mutations = {
  [types.MESSAGE_LOAD] (state, payload) {
    state.messageId = payload ? payload.id : 0
    state.messageContent = payload ? payload.content : ''
    state.isMessageEnabled = payload ? payload.enabled : false
  }
}

export default {
  state,
  getters,
  actions,
  mutations
}

and I have a global action (action.js) the gets multiple data:

export const loadSetting = ({ commit, rootGetters }) => {
  api.fetchAsync('api/Preference/all', rootGetters.token)
  .then((data) => {
    commit(types.MESSAGE_LOAD, data.message)
    commit(types.HELPDESK_LOAD, data.helpDesk)
    commit(types.VOLUME_LOAD, data.volumes)
    commit(types.DOWNLOAD_LOAD, data.downloadService)
  })
}

My api call:

  async fetchAsync (url, token = '') {
    let data = await axios.get(HOST + url, {
      headers: {
        'Authorization': 'bearer ' + token
      }
    })
    return data
  }
1
Shouldn't it be this.$data.msg.id ?Thomas
no, that didn't work.capiono
Can you share your vuex-store file?Onur Özkan
I have added the store.capiono

1 Answers

1
votes

The problem is your'e calling an async method in Vuex but in the created method, you're treating it like a sync operation and expect to get a value.

You need to use the computed properties you created since they are reactive and will update on every change. In order to make the computed writeable change it to be like this:

    computed: {
       ...mapGetters({
          messageId: 'messageId',              
          isMessageEnabled: 'isMessageEnabled',
          isMessageValid: 'isMessageValid'
        }),
        messageContent(){
            get () {
               return this.$store.getters.messageContent
            },
            set (value) {
               //this is just an example, you can do other things here
               this.$store.commit('updateMessage', value)
            }
        }
    }

And change the html to use messageContent:

<b-form-textarea id="content" v-model="messageContent" :rows="3" required aria-required="true" maxlength="250"></b-form-textarea>

For more info refer to this: https://vuex.vuejs.org/en/forms.html