Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vuex input with v-model not reactive

I try to explain it as simple as possible. I have something like this. Simple Vue root, Vuex store and input with v-model inside navbar id.

That input is not reactive... Why?!

enter image description here

enter image description here

HTML

<div id="navbar">
    <h2>@{{ test }}</h2>
    <input v-model="test" />
</div>

store.js

import Vuex from 'vuex'

export const store = new Vuex.Store({
  state: {
    test: 'test'
  },
  getters: {
    test (state) {
      return state.test
    }
  }
})

Vue Root

import { store } from './app-store.js'

new Vue({
  el: '#navbar',
  store,
  computed: {
    test () {
      return this.$store.getters.test
    }
  }
})
like image 914
Krystus Avatar asked Mar 13 '17 01:03

Krystus


3 Answers

You're binding to a computed property. In order to set a value on a computed property you need to write get and set methods.

computed:{
    test:{
        get(){ return this.$store.getters.test; },
        set( value ){ this.$store.commit("TEST_COMMIT", value );}
    }
}

And in your store

mutations:{
    TEST_COMMIT( state, payload ){
        state.test=payload;
    }
}

Now when you change the value of the input bound to test, it will trigger a commit to the store, which updates its state.

like image 169
czarchaic Avatar answered Oct 17 '22 22:10

czarchaic


You can easily use v-model with Vuex (with actions/mutations firing on each change) by using my library:

https://github.com/yarsky-tgz/vuex-dot

<template>
  <form>
    <input v-model="name"/>
    <input v-model="email"/>
  </form>
</template>

<script>
  import { takeState } from 'vuex-dot';

  export default {
    computed: {
      ...takeState('user')
        .expose(['name', 'email'])
        .commit('editUser') // payload example: { name: 'Peter'}
        .map()
    }
  }
</script>
like image 44
Yaroslav Dobzhanskij Avatar answered Oct 17 '22 20:10

Yaroslav Dobzhanskij


You don't want to use v-model for that. Instead, use @input="test" in your input field and in the your methods hook:

 test(e){
    this.$store.dispatch('setTest', e.target.value)
 }

Inside your Vuex store:

In mutations:

   setTest(state, payload){
      state.test = payload
   },

In actions:

setTest: (context,val) => {context.commit('setTest', val)},

The input should now be reactive and you should see the result in @{{test}}

Here is an example of how I handle user input with Vuex: http://codepen.io/anon/pen/gmROQq

like image 21
Mahmud Adam Avatar answered Oct 17 '22 22:10

Mahmud Adam