最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Vuex : state change not updating input field - Stack Overflow

programmeradmin1浏览0评论

**** UPDATE ****

Solution : Not bothering to tie the Vuex state to the form. I realized it's not worth the trouble, and I can still serialize the form data and send it along anyway using the standard conventions. Had a total rethinking of not needing to tie so many elements into JS objects.

**** ORIG ****

Alright, can someone please tell me what I'm missing here.

I want to update the state in a mutation function, and have the changes reflect in the input fields. Crazy right? I guess there's trouble with updating object properties, so in the example I have both referencing the object property and defining a specific getter for the property, neither of which are working. Then to represent updating the state outside of the input field, I just have a button below that does this.

Template:

<input :value="user.first_name" @input="UPDATE_USER" />
OR
<input :value="first_name" @input="UPDATE_USER" />
<button v-on:click="updateName">Update</button>

Component:

puted: {
   ...mapState({
        user: state => state.user,
        first_name: state => state.user.first_name // specific getter for the property
    })
},
methods: {
    ...mapActions([
        UPDATE_USER,
    ]),
    updateName () {
        this.$store.dispatch(UPDATE_USER_NAME, "anything");
    }
}

Action:

[UPDATE_USER_NAME] ({mit}, name) {
    mit("updateUserName", name);
},
// Omitted UPDATE_USER function, just takes e.target.name / value and it works anyway

Mutations:

updateUserName (state, name) {
    Vue.set(state.user, "first_name", name);
}

Expected: Click the button, it updates the state, and the input field value shows "anything".

Actual: Click the button, it updates the state, but the input field value is not updated. This goes for both input fields, one which references the object property directly, and the other which has its own getter.

Editing the input fields works fine, so it's like it works top-down but not bottom-up. What the heck am I missing?

**** UPDATE ****

Solution : Not bothering to tie the Vuex state to the form. I realized it's not worth the trouble, and I can still serialize the form data and send it along anyway using the standard conventions. Had a total rethinking of not needing to tie so many elements into JS objects.

**** ORIG ****

Alright, can someone please tell me what I'm missing here.

I want to update the state in a mutation function, and have the changes reflect in the input fields. Crazy right? I guess there's trouble with updating object properties, so in the example I have both referencing the object property and defining a specific getter for the property, neither of which are working. Then to represent updating the state outside of the input field, I just have a button below that does this.

Template:

<input :value="user.first_name" @input="UPDATE_USER" />
OR
<input :value="first_name" @input="UPDATE_USER" />
<button v-on:click="updateName">Update</button>

Component:

puted: {
   ...mapState({
        user: state => state.user,
        first_name: state => state.user.first_name // specific getter for the property
    })
},
methods: {
    ...mapActions([
        UPDATE_USER,
    ]),
    updateName () {
        this.$store.dispatch(UPDATE_USER_NAME, "anything");
    }
}

Action:

[UPDATE_USER_NAME] ({mit}, name) {
    mit("updateUserName", name);
},
// Omitted UPDATE_USER function, just takes e.target.name / value and it works anyway

Mutations:

updateUserName (state, name) {
    Vue.set(state.user, "first_name", name);
}

Expected: Click the button, it updates the state, and the input field value shows "anything".

Actual: Click the button, it updates the state, but the input field value is not updated. This goes for both input fields, one which references the object property directly, and the other which has its own getter.

Editing the input fields works fine, so it's like it works top-down but not bottom-up. What the heck am I missing?

Share Improve this question edited Feb 9, 2019 at 6:18 coleman-benjamin asked Feb 9, 2019 at 3:24 coleman-benjamincoleman-benjamin 9511 gold badge15 silver badges29 bronze badges 3
  • Why not mapActions UPDATE_USER_NAME and call it like this.UPDATE_USER_NAME(name) ? – vapurrmaid Commented Feb 9, 2019 at 3:33
  • Is there a reason v-model can't be used within the ponent, and values in state are only updated on an action method? The <input> could still be initialized with a value from the store. – vapurrmaid Commented Feb 9, 2019 at 3:46
  • Yeah I'm playing around with v-model and using get() set() to handle updates, unfortunately with the same result. In fact the example I have updates via action, see it's passed into @input – coleman-benjamin Commented Feb 9, 2019 at 4:19
Add a ment  | 

3 Answers 3

Reset to default 4

Note: I tested this locally but I don't know exactly how the store state looks from the question.

The <input> can be two-way bound with v-model, instead of puted or watched. It can be initialized with a value from the store (I used the mounted lifecycle hook below). The store state is updated only on button click.

<input v-model="firstName"/>
<button @click="updateName">Update</button>
import { mapActions, mapGetters } from 'vuex'

export default {
  data () {
    return {
      firstName: ''
    }
  },
  
  puted: mapGetters(['getFirstName']),

  methods: {
    ...mapActions(['UPDATE_FIRST_NAME']), // get the action from the store

    updateName () {
      // validations can go here etc
      this.UPDATE_FIRST_NAME(this.firstName) // update vuex store state
    }
  },

  mounted () {
    this.firstName = this.getFirstName // initialize this.firstName -> <input> 
  }
}

With this solution, you'd have to make sure to create the getter in your store, as in the following example:

const state = {
  user: {
    firstName: ''
  }
}

const getters = {
  getFirstName: state => state.user.firstName
}

You need to watch the state variables. When it change the value, the the watch function will fire.

 export default {
    data() {
        return {
            dummy_name: '',
            first_name: '',
        }
    },
    created(){
    },
    puted: {
        dummy_name() {
            return this.$store.state.user.first_name
        },
    watch: {
       dummy_name() {
            this.first_name = this.dummy_name
       }
    }

Hope this will help, and get some idea how watch and puted work.

This is an old question, but I ran into the same problem yesterday and the solution was to use the .prop modifier on the input value attribute like so:

<input :value.prop="first_name" @change="updateName" />

A quote from quite random place in the docs says:

For some properties such as value to work as you would expect, you will need to bind them using the .prop modifier.

Hope this helps someone!

发布评论

评论列表(0)

  1. 暂无评论