Менять родительскую переменную в дочернем компоненте
В родительском компоненте есть переменная которая отвечает за состояние checkbox и нужно менять ее в дочернем компоненте при нажатии на checkbox, подскажите что я делаю неправильно и как можно это исправить?
РОДИТЕЛЬСКИЙ ЭЛЕМЕНТ
<template>
<div class="contact-form">
<form @submit.prevent="sendMail">
<div class="contact-form__actions">
<button type="submit">Send</button>
<CheckBoxInput
model="mail.newsletterSub"
id="contact-terms"
:label="checkboxOptions.label"
:dark="checkboxOptions.dark"
/>
</div>
</form>
</div>
</template>
<script>
import CheckBoxInput from "@/components/inputs/CheckBoxInput";
export default {
name: "ContactUsForm",
components: {
CheckBoxInput,
},
data() {
return {
mail: {
newsletterSub: false,
},
};
},
methods: {
sendMail(e) {
e.preventDefault();
this.mail = {
newsletterSub: false,
};
},
},
};
</script>
ДОЧЕРНИЙ CHECKBOX
<template>
<div :class="[`checkbox-input`, `${dark ? 'checkbox-input_dark' : ''}`]">
<input :id="id.replace(' ', '')" type="checkbox" v-model="model" />
<label class="body-3" :for="id.replace(' ', '')">
{{ label }}
</label>
</div>
</template>
<script>
export default {
name: "CheckBoxInput",
props: {
value: {},
id: {
type: String,
required: true,
},
label: {
type: String,
required: true,
},
dark: {
type: Boolean,
default: false,
},
},
methods: {
},
computed: {
model: {
get() {
return this.value;
},
set(value) {
this.$emit("change", value);
},
},
},
};
</script>
Ответы (2 шт):
Автор решения: Дмытрык
→ Ссылка
const CheckBox = Vue.component("CheckBox", {
template: `<div>
<label> <input type="checkbox" v-model="value"></input>Checkbox</label>
</div>`,
props: {
checkBox: {
type: Boolean
},
},
model: {
event: "change",
},
data() {
return {
value: this.checkBox,
};
},
watch: {
value: function(e) {
this.$emit("change", e);
},
},
});
const app = new Vue({
el: "#app",
components: {
CheckBox
},
template: `<CheckBox v-model='value' :checkBox="value"></CheckBox>`,
data() {
return {
value: true,
};
},
// для визуализации изменений в родительском компоненте
watch: {
value: function(e) {
console.log(e);
},
},
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<div id="app"></div>
Автор решения: Максим Вишневский
→ Ссылка
Для реализации такой логики вам необходимо обратиться к разделу документации о работе с emit для настройки v-model. Ниже пример использования данного подхода (может возникнуть вопрос о разнице между эвентами change и input, тут данный хороший ответ):
const CheckBox = Vue.component("CheckBox", {
template: `
<div>
<label>
<input type="checkbox" v-model="localValue"/>
Checkbox
</label>
</div>
`,
model: {
event: 'change',
prop: 'value',
},
props: {
value: {
type: Boolean,
required: true,
},
},
computed: {
// Объявляем вычисляемое свойство с геттером и сеттером
// чтобы не делать промежуточную локальную переменную и вотчер
localValue: {
get() {
return this.value;
},
set(newValue) {
this.$emit('change', newValue);
},
},
},
});
const app = new Vue({
el: "#app",
components: {
CheckBox,
},
template: `
<div>
<CheckBox v-model='value'></CheckBox>
Result: {{ value }}
</div>
`,
data() {
return {
value: true,
};
},
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<div id="app"></div>
Ответ основан на ответе участника Дмытрык, данный выше и содержит некоторые правки для оптимизации кода и ознакомительную информацию.