问题
I'm trying to build a custom checkbox component with options that are generated with a v-for loop from an array with options and values. How can I bind the v-model correctly to the checkbox component so that it's correctly updated?
The problem now is that the model only updates to the latest checkbox that is checked and does not give an array with all checked options.
Vue.component('ui-checkbox', {
props: {
label: {
type: String,
required: true,
},
index: {
type: Number
},
inputValue: {
type: String
}
},
methods: {
onChange(e) {
this.$emit('input', e.target.value);
},
},
template: `<div>
<input
:id="index"
type="checkbox"
:value="inputValue"
@change="onChange" />
<label :for="index">
{{ label }}
</label>
</div>`,
})
new Vue({
el: "#app",
data: {
checkOptions: [
{
label: 'Option 1',
value: 'value of option 1',
},
{
label: 'Option 2',
value: 'value of option 2',
},
{
label: 'Option 3',
value: 'value of option 3',
},
{
label: 'Option 4',
value: 'value of option 4',
},
],
myCheckBoxModel: []
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<span>checked Checkboxes: {{ myCheckBoxModel }} </span>
<ui-checkbox
v-for="(option, index) in checkOptions"
v-model="myCheckBoxModel"
:key="index"
:index="index"
:input-value="option.value"
:label="option.label" />
</div>
回答1:
When you do
this.$emit('input', e.target.value);
it works like
myCheckBoxModel = e.target.value
So it just assigns the value of the last checkbox you clicked to myCheckBoxModel
.
If you want to keep all checked items in myCheckBoxModel
, you need to do the following:
- add
value
property toui-checkbox
component to have access to the current value ofmyCheckBoxModel
.Value
is default property name for this goal (see vue guide). - in your
onChange
method copy the current value to the variable, because it's not good to mutatevalue
property directly - if your checkbox is checked, push the correspondent value to the array. If the checkbox is not checked, delete to correspondent value from the array
- emit
input
event with the resulting array as value
Vue.component('ui-checkbox', {
props: {
label: {
type: String,
required: true,
},
index: {
type: Number
},
inputValue: {
type: String
},
value: {
type: Array
}
},
methods: {
onChange(e) {
let currentValue = [...this.value]
if (e.target.checked) {
currentValue.push(e.target.value)
} else {
currentValue = currentValue.filter(item => item !== e.target.value)
}
this.$emit('input', currentValue);
},
},
template: `<div>
<input
:id="index"
type="checkbox"
:value="inputValue"
@change="onChange" />
<label :for="index">
{{ label }}
</label>
</div>`,
})
new Vue({
el: "#app",
data: {
checkOptions: [
{
label: 'Option 1',
value: 'value of option 1',
},
{
label: 'Option 2',
value: 'value of option 2',
},
{
label: 'Option 3',
value: 'value of option 3',
},
{
label: 'Option 4',
value: 'value of option 4',
},
],
myCheckBoxModel: []
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
checked Checkboxes:
<span v-for="item in myCheckBoxModel"> {{ item }}; </span>
<ui-checkbox
v-for="(option, index) in checkOptions"
v-model="myCheckBoxModel"
:key="index"
:index="index"
:input-value="option.value"
:label="option.label" />
</div>
I don't know if you need to set checkbox state programmatically, i.e. when you change myCheckBoxModel
the state of checkboxes changes correspondently. If you do, you need to watch value
property in your ui-checkbox
component: set the state of the check box in dependance of if its value is in value
array. Do the same also in created
hook if you want to initialize the state of checkboxes by myChexkboxModel
来源:https://stackoverflow.com/questions/58187290/vue-binding-with-v-model-in-custom-checkbox-component-doesnt-work