Vue 3 v-model not working with custom input component in Nuxt.js - vue.js

I am trying to use a custom Vue input component with a v-model, but the value is not updating in the parent component. I am using Vue 3 with Nuxt.js.
Here is my custom input component:
<template>
<input
type="text"
:value="modelValue"
#input="$emit('update:modelValue', $event.target.value)"
:placeholder="placeholder"
class="border border-gray-300 rounded-lg w-full p-2 text-black m-1"
/>
</template>
<script setup>
const props = defineProps({
modelValue: String,
placeholder: String,
});
const emit = defineEmits(["update:modelValue"]);
</script>
<script>
export default {
name: "MyInput",
};
</script>
And here is how I am using it in the parent component:
<template>
<div>
<MyInput v-model="inputValue" placeholder="Enter a value" />
</div>
</template>
<script>
import MyInput from "./MyInput.vue";
export default {
name: "MyParentComponent",
components: {
MyInput,
},
data() {
return {
inputValue: "",
};
},
};
</script>
The inputValue data property is not being updated when I type in the input field. Can someone help me figure out what I'm doing wrong?
I have a Vue 3 project without Nuxt.js using this exact same code and it works there.

there is no mistake in your codes I used exact same code and it's working with no problem
but:
there is no need to import components (Nuxt supports auto import)
your file's structure should be like this:
|__components
|
|__MyInput.vue
|
|__MyParentComponent.vue
|__app.vue
MyInput.vue
<template>
<input
type="text"
:value="modelValue"
#input="$emit('update:modelValue', $event.target.value)"
:placeholder="placeholder"
class="border border-gray-300 rounded-lg w-full p-2 text-black m-1"
/>
</template>
<script setup>
const props = defineProps({
modelValue: String,
placeholder: String,
});
const emit = defineEmits(["update:modelValue"]);
</script>
the dev tools will show the name of the component. So no additional naming is necessary.
MyComponent.vue
<template>
<div>
<MyInput v-model="inputValue" placeholder="Enter a value" />
<p>{{ inputValue }}</p>
</div>
</template>
<script setup>
let inputValue = ref("");
</script>
app.vue
<template>
<MyComponent />
</template>

Related

Is it possible to use a prop as a v-model value?

Is it possible to use the value of a prop as the input's v-model?
I normally do the following when creating an input:
<template>
<form>
<input v-model="form.email" type="email"/>
</form>
</template>
<script>
export default {
data() {
return {
form: {
email: '',
}
}
}
}
</script>
But now I'm trying to achieve the following where this.myProp is used within the v-model without being displayed as a string on the input:
<template>
<form>
<input v-model="this.myProp" type="email"/>
</form>
</template>
<script>
export default {
props: ['myProp'] // myProp = form.email for example (to be handled in a parent component)
}
</script>
Yes, but while using it in parent component. In child component you need to extract value and #input instead of using v-model (v-model is shortcut for value="" and #input) Here is an example of input with label, error and hint in Vue 3 composition API.
BaseInput.vue
<template>
<div class="flex flex-col">
<label>{{ label }}</label>
<input v-bind="$attrs" :placeholder="label" :value="modelValue" #input="$emit('update:modelValue', $event.target.value)">
<span v-for="item of errors" class="text-red-400">{{ item.value }}</span>
<span v-if="hint" class="text-sm">{{ hint }}</span>
</div>
</template>
<script setup>
defineProps({ label: String, modelValue: String | Number, errors: Array, hint: String })
defineEmits(['update:modelValue'])
</script>
Using v-bind="$attrs" you target where attributes like type="email" need to be applied in child component. If you don't do it, it will be added to the top level DOM element. In above scenario <div>.
ParentComponent.vue
<BaseInput type="email" v-model="formData.email" :label="Email" :errors="formErrors.email"/>

Vue.js Child Component not Updating Data in Parent Component

I am using vue components in a Laravel project.
I have taken sample code from https://vuejs.org/guide/components/events.html#usage-with-v-model
I have a child component with an input box:
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>
<template>
<input
:value="modelValue"
#input="$emit('update:modelValue', $event.target.value)"
/>
</template>
This component is being used in a parent component.
<phone-input v-model="phone"/> {{phone}}
The parent component displays the input box with the initial value of the phone variable. However, the changed value is not reflected in the parent's phone variable ( {{phone}} does not update). Am I missing something? I have cleared the cache, but it did not help.
I tried another variation of the code (from vue.js documentation code) as given here. However, this also does not work.
Parent
<MyComponent v-model:title="bookTitle" />. {{bookTitle}}
<!-- Child Component MyComponent.vue -->
<script>
export default {
props: ['title'],
emits: ['update:title']
}
</script>
<template>
<input
type="text"
:value="title"
#input="$emit('update:title', $event.target.value)"
/>
</template>
Thanks for your help.
Take a look at following snippet, looks ok:
const app = Vue.createApp({
data() {
return {
phone: "0123456"
}
},
})
app.component('phoneInput', {
template: `
<input
:value="modelValue"
#input="$emit('update:modelValue', $event.target.value)"
/>
`,
props: ['modelValue'],
emits: ['update:modelValue'],
})
app.mount("#demo")
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<phone-input v-model="phone"></phone-input>
{{ phone }}
</div>
<script>
export default {
props: ['modelValue'],
}
</script>
<template>
<input
:value="modelValue"
#input="$emit('input', $event.target.value)"
/>
</template>
You need specially emit input to make it work

Dynamic Placeholder in Vue 3 with Global Component

I am trying to set dynamic text for the placeholder attribute on my search bar. Depending on the page, I want the text in the search bar to be different (I will define it in data()).
However, since the search bar component is a global component, it doesn't seem to be editable.
(As you see below is my try, I did it with v-model based on Vue docs, however when I try with placeholder it doesn't work...)
Snippet 1 - Search bar component
<template>
<!-- Search Componenet -->
<div class="mx-5 mb-3 form-group">
<br>
<input class="mb-5 form-control" type="search" :placeholder="placeholderValue" :value="modelValue" #load="$emit('update:placeholderValue', $event.target.value)" #input="$emit('update:modelValue', $event.target.value)" />
</div>
</template>
<script>
export default {
props: ['modelValue', 'placeholderValue'],
emits: ['update:modelValue', 'update:placeholderValue']
}
</script>
Snippet 2 - Album.vue
<template>
<div class="AlbumView">
<h1>{{header}}</h1>
<h2>{{header2}}</h2>
<br>
<!-- Search Componenet -->
<SearchComponent :placeholder="placeholderValue" v-model="searchQuery" />
<!-- Dynamic Song Route Button -->
<div class="button-container-all mx-5 pb-5">
<div v-for="item in datanew" :key="item.id">
{{ item.album }}
</div>
</div>
</div>
</template>
<script>
import { datatwo } from '#/data2'
export default {
data() {
return {
placeholderValue: "Search for Albums here...",
datanew: datatwo,
searchQuery: null,
header: "Browse by Album",
header2: "Select an Album:",
publicPath: process.env.BASE_URL
};
},
}
</script>
If this is possible?
If you want to do it with v-model (the Childcomponent changes the value of the placeholder) you have to use v-model:placeholder for it to work.
And also placeholderValue is not the way to go the "Value" at the end of a prop is only needed for modelValue which is the default v-model-binding (v-model="") but if you want named v-model-binding (v-model:placeholder="") you do not want to add the "Value" in the props and emits arrays.
Example:
usage of SearchComponent
<SearchComponent :placeholder="'placeholderValue'" v-model="searchQuery" />
instead of 'placeholderValue' you can put any string you want or variable. I just put the string 'placeholderValue' as an example.
SearchComponent
<template>
<!-- Search Componenet -->
<div class="mx-5 mb-3 form-group">
<br>
<input class="mb-5 form-control" type="search" :placeholder="placeholder" :value="modelValue" #load="$emit('update:placeholderValue', $event.target.value)" #input="$emit('update:modelValue', $event.target.value)" />
</div>
</template>
<script>
export default {
name: "SearchComponent",
props: ['modelValue', 'placeholder'],
emits: ['update:modelValue'],
}
</script>
<style scoped>
</style>

Using parent prop on child function

please help me understand what I'm doing wrong here:
I have a child component that receives a prop from its parent. I want to extract part the first character of that prop value inside the child component, but I'm getting an "undefined" error. Here's the code:
Parent Component:
Child Component:
<template>
<div class="form-group">
<label>{{ label }}</label>
<div class="form-check form-check-inline">
<input
class="form-check-input"
type="text"
id="inputAgno"
v-model="aaaa"
/>
</div>
</div>
</template>
<script>
export default {
props: ["label", "value"],
computed:{
aaaa: function() {
return this.alta_establecimiento.subStr(0,4)
},
}
};
</script>
Thanks in advance!

vue how to access v-model from child component

my child component is like this
<editor v-model="edit_thread.body"></editor>
and then I access the component from inside like this
<template>
<div>
<input :value="this.value">
</div>
</template>
<script>
export default {
data() {
return {
value: this.edit_thread.body
}
}
}
</script>
not working, I miss something?
To use v-model on custom components, the component needs to:
have a prop (not a data property) named value:
<template>
<div>
<input :value="value">
</div>
</template>
<script>
export default {
props: ['value']
}
</script>
and emit an input event with new values:
<template>
<div>
<input #input="$emit('input', $event.target.value)">
</div>
</template>
demo