v-model для группы checkbox компонентов
Необходимо реализовать v-model для группы checkbox. Код который я написал:
Vue.config.productionTip = false
Vue.config.devtools = false
new Vue({
el: '#app',
// CheckboxComponent
components: {
CheckboxComponent: {
props: ['value', 'label'],
template: `
<div class="checkbox">
<label>
<input
type="checkbox"
:checked="value"
@input="$emit('input', $event.target.checked)"
>
<span>{{ label }}</span>
</label>
</div>
`
}
},
// End of CheckboxComponent
data() {
return {
checked: [],
someData: [
{ id: 0, name: 'Name 0' },
{ id: 1, name: 'Name 1' },
{ id: 2, name: 'Name 2' },
{ id: 3, name: 'Name 3' },
{ id: 4, name: 'Name 4' },
{ id: 5, name: 'Name 5' }
]
}
}
})
*{margin:0;padding:0;box-sizing:border-box;}#app{padding:1rem;}ul{list-style:none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in someData" :key="item.id">
<checkbox-component :label="item.name" v-model="checked"/>
</li>
</ul>
{{ checked }}
</div>
На данный момент, получилось что-то реализовать, но мне возвращает true/false всех checkbox, а нужно чтобы в массив checked: [], попадал label, или еще лучше - value, активного checkbox-component
Результат который нужно получить, но с кастомным компонентом. Прошу помочь с решением!
Ответы (1 шт):
Объявляете внутри вложенного компонента в data свойство (допустим) checkedP:
data() {
return {
checkedP: false
}
},
в computed объявляете:
computed: {
checked: {
get() {
return this.value
},
set(val) {
this.checkedP = val
}
}
},
, этот метод будет формировать текущее актуальное состояние этого вложенного компонента и в итоге либо вернет текущее состояние (полученное из props), либо модифицирует его (если произойдет событие).
template оформляете следующим образом:
template: `
<div class="checkbox">
<label>
<input
type="checkbox"
v-model="checked"
:value="item"
@change="onChange"
>
<span>{{ item.name }}</span>
</label>
</div>
`,
Соответственно добавляете метод для обработки события на input:
methods: {
onChange(e) {
this.$emit('input', this.checkedP)
}
}
Таким образом, инициируя событие изменения состояния input, вы вызываете метод onChange, в результате работы которого в родительский компонент будет отправлено новое состояние текущего компонента (заметьте за это состояние отвечает метод checked из computed текущего вложенного компонента), в свою очередь родитель синхронизирует это состояние со своими моделями, а именно v-model="checked"
Привожу ваш пример с указанными модификациями.
new Vue({
el: '#app',
// CheckboxComponent
components: {
CheckboxComponent: {
props: ['value', 'item'],
data() {
return {
checkedP: false
}
},
computed: {
checked: {
get() {
return this.value
},
set(val) {
this.checkedP = val
}
}
},
template: `
<div class="checkbox">
<label>
<input
type="checkbox"
v-model="checked"
:value="item"
@change="onChange"
>
<span>{{ item.name }}</span>
</label>
</div>
`,
methods: {
onChange(e) {
this.$emit('input', this.checkedP)
}
}
}
},
// End of CheckboxComponent
data: {
checked: [],
someData: [{
id: 0,
name: 'Name 0'
},
{
id: 1,
name: 'Name 1'
},
{
id: 2,
name: 'Name 2'
},
{
id: 3,
name: 'Name 3',
checked: true
},
{
id: 4,
name: 'Name 4'
},
{
id: 5,
name: 'Name 5'
}
]
}
})
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#app {
padding: 1rem;
}
ul {
list-style: none;
display: flex;
justify-content: space-between;
}
li {
flex: 1 1 auto;
background: #ccc;
padding: 10px;
margin: 5px;
border-radius: 5px;
}
label {
cursor: pointer;
}
.pre {
display: block;
background: #eee;
font-size: 14px;
padding: 10px;
border-radius: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
<ul>
<li v-for="item in someData" :key="item.id">
<checkbox-component :item="item" v-model="checked" />
</li>
</ul>
<div class="pre">
{{ checked }}
</div>
</div>