How to bind checkboxes to Vuex store?

2020-02-29 00:12发布

问题:

I have a component that contains some checkboxes. I need to be able to access which checkboxes are checked from other components in my Vue application, but I cannot for the life of me figure out (nor find online) how to properly connect the checkboxes to my Vuex store.

What is the right way to connect checkboxes within a component to a Vuex store, so that they act just as if the checkbox was connected to the components data via v-model?

Here is a starting point for what I'm trying to do (in a very very basic sense)

Code in jsfiddle below

https://jsfiddle.net/9fpuctnL/

The aim is to get the colours that are selected in the colour-checkboxes component to output in the chosen-colours component, going through the Vuex store.

回答1:

You can use computed property with getter as vuex getter and setter in computed property which will call a mutation for that state property to do this.

You can see an example of this here with two-way Computed Property:

<input v-model="message">
// ...
computed: {
  message: {
    get () {
      return this.$store.state.obj.message
    },
    set (value) {
      this.$store.commit('updateMessage', value)
    }
  }
}


回答2:

OK I have been challenged to show my solution. Here it is on jsfiddle

the html is:

<div id="app">
  <label v-for="brother in ['Harpo','Groucho','Beppo']">
    <input type='checkbox' v-model='theBrothers' v-bind:value='brother' />
      {{ brother }}
  </label>
  <div>
  You have checked: {{ theBrothers }}
  </div>
</div> 

and the js is:

const store = new Vuex.Store({
  state: {
    theBrothers: []
  },
})

new Vue({
  el: "#app",
  store: store,
  computed: {
    theBrothers: {
      set(val){this.$store.state.theBrothers = val},
      get(){ return this.$store.state.theBrothers }
    }
 },
}) 


回答3:

I wanted to provide an answer that actually uses checkboxes.

There is one possible solution outlined here: Vuex dynamic checkboxes binding

And a simpler solution can be achieved something like the following:

<div v-for="tenant in tenants" 
     v-bind:key="tenant.id" 
     class="form-group form-check">

<input type="checkbox" 
     class="form-check-input" 
     v-bind:id="tenant.id" 
     v-bind:value="tenant.name" 
     @change="updateSelectedTenants">

Key here is calling a method using on-change, it will pass an event to the method with all the details needed to make the change.

The @change function:

updateSelectedTenants(e) {
  console.log('e', e.target)
  console.log('e', e.target.value)
  this.$store.dispatch('updateSelectedTenants', e.target)
}

Here I want the value, in this case will be the tenants name, but further inspection of the target also gives the 'id', and whether or not the checkbox is 'checked' or unchecked.

Over in the store, we can manipulate the 'selectedTenants' array:

updateSelectedTenants (context, tenant) {
  if(tenant.checked) {
    // Tenant checked, so we want to add this tenant to our list of 'selectedTenants'
    context.commit('addSelectedTenant', { id: tenant.id, name: tenant.value })
  } else {
    // otherwise, remove the tenant from our list
    context.commit('removeSelectedTenant', tenant.id)
  }
}

Here are the actual mutators:

addSelectedTenant (state, tenant) {
  this.state.selectedTenants.push(tenant)
},
removeSelectedTenant (state, id) {
  this.state.selectedTenants = this.state.selectedTenants.filter(tenant => {
    return tenant.id != id
  })

The vuejs docs are great, but sometimes they can be a little light on with real world examples. I don't think it's possible to achieve the above using a computed value, with get(), set()... but I'd like to see a solution that can.



回答4:

Use @change to update Vuex as needed:

HTML:

<input
  v-for='item in items'
  @change='update_checkboxes'
  v-model='selected_checkboxes'
  :value='item.id'
  type='checkbox
/>
<label>{{item.name}}</label>

JS:

data: function(){ 
  return {
    selected_checkboxes: [] // or set initial state from Vuex with a prop passed in
  }
},
methods: {
  update_checkboxes: function(){
    this.$store.commit('update_checkboxes', this.selected_checkboxes)
  }
}


回答5:

You shoud remove colours = [] in data.