I'm quite new with Vue, and I'm trying to make a simple Input as reusable as possible, the props are working well, but it's not being reactive, and I don't understand why. For what I heard, in order to make a component v-model allowed it should
- first have a prop called: modelValue tied as :value="modelValue"
- And in second instance it should $emit() an event.
I'm doing both of them, and I'm not getting any reactive behavior, so here's my code: Input-Child Component:
<template>
<div >
<label for="base-input">{{ label }}</label>
<input
:placeholder="placeholder"
:value="modelValue"
@input="$emit('customChange:modelValue', $event.target.value)"
v-bind="$attrs"
id="base-input"
/>
</div>
</template>
<script>
export default {
name: "BaseInput",
props: {
label: {
type: String,
},
placeholder: {
type: String,
},
modelValue: {
type: [String, Number],
default: "",
required: true,
},
},
};
</script>
and here is the parent Component:
<template>
<div>
<form>
<h3>Name & describe your event</h3>
<BaseInput
label="Title"
type="text"
placeholder="Enter title..."
v-model="title"
/>
<BaseInput
label="Description"
type="text"
placeholder="Enter Description..."
v-model="description"
/>
<h1>{{ title }}</h1>
<h3>Where is your event?</h3>
<BaseInput
label="Location"
type="text"
placeholder="Enter Location..."
v-model="location"
/>
<button type="submit">Submit</button>
</form>
{{ description }}
{{ location }}
</div>
</template>
<script>
import { reactive, toRefs } from "vue";
import BaseInput from "../components/BaseInput.vue";
export default {
name: "MainForm",
components: {
BaseInput,
},
setup() {
const event = reactive({
category: "",
title: "2pacShakur",
description: "",
location: "",
pets: 1,
extras: {
catering: false,
music: false,
},
});
return {
...toRefs(event),
};
},
};
</script>
CodePudding user response:
Try to emit update:modelValue
:
const { reactive, toRefs } = Vue
const app = Vue.createApp({
setup() {
const event = reactive({
category: "",
title: "2pacShakur",
description: "",
location: "",
pets: 1,
extras: {
catering: false,
music: false,
},
});
return {
...toRefs(event),
};
},
})
app.component('BaseInput', {
template: `
<div >
<label for="base-input">{{ label }}</label>
<input
:placeholder="placeholder"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
v-bind="$attrs"
id="base-input"
/>
</div>
`,
props: {
label: {
type: String,
},
placeholder: {
type: String,
},
modelValue: {
type: [String, Number],
default: "",
required: true,
},
},
})
app.mount('#demo')
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
<div>
<form>
<h3>Name & describe your event</h3>
<base-input
label="Title"
type="text"
placeholder="Enter title..."
v-model="title"
></base-input>
<base-input
label="Description"
type="text"
placeholder="Enter Description..."
v-model="description"
></base-input>
<h1>{{ title }}</h1>
<h3>Where is your event?</h3>
<base-input
label="Location"
type="text"
placeholder="Enter Location..."
v-model="location"
></base-input>
<button type="submit">Submit</button>
</form>
{{ description }}
{{ location }}
</div>
</div>