Exploring the use of v-model in Vue3 child components

After some exploration, I recently discovered that in Vue3, the v-model functionality does not work responsively or reactively with child Component.

The following code snippet showcases how the username data gets updated:

<template>
  <div>
    <input type="text" v-model="username" placeholder="Insert your username" />
    <p>{{ username }}</p>
  </div>
</template>

<script>
// Home.vue
export default {
  name: 'Home',
  data() {
    return {
      username: 'admin'
    }
  }
}
</script>

When text is entered into the input, the username data will also change accordingly.

However, when utilizing a Component as shown below:

<template>
    <input type="text" :class="'input-text ' + additionalClass" :placeholder="placeholder" />
</template>

<script>
// InputText.vue
import { defineComponent } from "vue"

export default defineComponent({
    name: 'InputText',
    props: {
        placeholder: {
            type: String,
            default: ''
        },
        additionalClass: {
            type: String,
            default: ''
        }
    }
})
</script>

I decided to update my code and incorporate the Component.

Please note that the Component has been successfully registered.

<template>
  <div>
    <input-text v-model="username" :placeholder="`Insert your username`" />
    <p>{{ username }}</p>
  </div>
</template>

<script>
// Home.vue
export default {
  name: 'Home',
  data() {
    return {
      username: 'admin'
    }
  }
}
</script>

Upon entering text, I noticed that the username data did not get updated, unlike the previous scenario. This issue led me to ponder if there exists a solution or at least a reference to what I am aiming to achieve.

Answer №1

Utilizing Vue3's script setup feature for more concise syntax

<template>
  <input type="text" v-model="val" @input="handleInput">
</template>

<script setup>
import {ref, defineProps, defineEmits, watch} from 'vue'

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
})
const emit = defineEmits(['update:modelValue'])

const val = ref('')

watch(() => props.modelValue, newValue => val.value = newValue, {
  immediate: true
})

const handleInput = () => emit('update:modelValue', val.value)
</script>

Answer №2

It is important to note that simply using v-model will not automatically update the underlying element. You will still need to handle this functionality within the component itself by exposing modelValue as a prop for it to function correctly. Here is an example of how you can achieve this:

<template>
  <input
    type="text"
    @input="handleInputChange"
    :value="modelValue"
    :class="'input-text ' + customClass"
    :placeholder="placeholderText" />
</template>

<script>
  // CustomInput.vue
  import { defineComponent } from "vue"

  export default defineComponent({
    name: 'CustomInput',

    emits: ['update:modelValue'],

    props: {
      modelValue: String,
      placeholderText: {
        type: String,
        default: ''
      },
      customClass: {
        type: String,
        default: ''
      }
    },

    setup(props, { emit }) {
      function handleInputChange(e) {
        emit('update:modelValue', e.currentTarget.value);
      }

      return {
        handleInputChange
      }
    }
  })
</script>

Answer №3

If you're looking for an easier way to manage v-model in a sub-component, check out the VueUse helper called useVModel. You can find more information at this link.

<script lang="ts" setup>
import { useVModel } from '@vueuse/core'

const props = defineProps<{
  modelValue: string
}>()
const emit = defineEmits(['update:modelValue'])

const model = useVModel(props, 'modelValue', emit)
</script>

<template>
    <input type="text" v-model="model" />
</template>

Answer №4

utilizing the OPTIONS API format

<template>
    <input type="text" v-model="val" @input="updateText" :value="modelValue">
</template>

<script scoped>
    export default {
        props: {
            modelValue: String,
        },
        methods: {
            updateText(event){
                this.$emit('update:modelValue', event.currentTarget.value)
            }
        }
    }
</script>

Answer №5

Back in the day, this code used to work perfectly fine:

Your InputText element

<template>
    <input :value="value"
           @input="({target}) => $emit('input', target.value)"/>
</template>

<script>
    export default {
        props: {
            value: {}
        }
    }

Your main component

<template>
    <inputText v-model="inputValue"/>
</template>

<script>
    export default {
        components: {inputText},
        data: () => ({
            inputValue: null
        })
    }
</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unveiling the Magic: Enhancing Raphaeljs with Interactive Click Events on a Delicious Slice of the

I'm having trouble responding to a click event on each slice of a Raphael Pie Chart. I've tried implementing the code below, but it doesn't seem to be working. The code is just two lines, commented as "My Code", in the example from the offic ...

Guide on altering the background color of a table row depending on the data in its cells with the help of AngularJS

I am looking to dynamically change the background color of a row based on specific cell data. If the first four characters in a table cell match a certain value, I want the entire row to change its color to red. Currently, my code changes the row color ba ...

The loader fails to disappear even after the AJAX response has been received

I am currently working on a page that utilizes AJAX to display data. While the data is being fetched, I want to show a loading animation, and once the data has been retrieved, I want the loader to disappear. Below is a snippet of the code where I am attemp ...

Update tailwindcss color dynamically according to user input within Vue3/Nuxt3

I am currently exploring a method to allow users to specify the primary color of a website. When defining my Tailwind classes, I aim to utilize something like bg-primary-600 instead of directly inputting a color. This way, if the value for primary changes, ...

What is the best way to eliminate concealed divs from the view source of a webpage?

On my HTML page, I have some hidden DIVs that can still be viewed in the page source. I want to ensure that these DIVs are not visible to users when they inspect the page source. Is there a way to achieve this using Javascript or another solution? ...

What is the best way to implement ES2023 functionalities in TypeScript?

I'm facing an issue while trying to utilize the ES2023 toReversed() method in TypeScript within my Next.js project. When building, I encounter the following error: Type error: Property 'toReversed' does not exist on type 'Job[]'. ...

Using jQuery, check if the input contains any phrases from the array that are suitable for children

I stumbled upon some code designed for a chat system. My plan is to implement it as a child-friendly global chat, so that I can avoid any blame associated with inappropriate content. The basic premise of the code involves checking user input against an arr ...

Why is it that when I refresh the page in Angular, my logged-in user is not being recognized? What could be causing this

I am developing a Single Page Application using the combination of Angular JS and Node JS. In my HTML file, I have defined two divs and based on certain conditions, I want to display one of them using ng-if. However, I noticed that the model value used in ...

Failure to fetch data through Axios Post method with a Parameter Object

I've encountered an issue with Axios while attempting to make a post request with a parameters object to a Laravel route. If I use query parameters like ?username=user, the post request works successfully. However, when I use an object, it fails: Be ...

The Javascript function will keep on executing long after it has been invoked

I am currently facing an issue with calling a JavaScript function within an AJAX call. The progress function below is supposed to be executed every time the for loop runs. However, the problem is that although progress is being run as many times as the for ...

Is it considered good or bad practice to use plain JavaScript objects in an AngularJS application?

Imagine needing a custom object that doesn't rely on AngularJS (such as a specific collection with unique functionalities). You could create it independently of AngularJS and simply use it in services/controllers. Alternatively, you could design it a ...

Interactive AJAX div click functionality

For this code to work, the user needs to first click the like button and then continue to proceed. However, I am having trouble getting the div event to function properly. The like button is located within a div called postos. When something is clicked wit ...

An error occurred while trying to access the stored data at https://localhost:5000. The SSL protocol encountered

I am attempting to utilize an API to retrieve data and transfer it to MongoDB from my React application to the Node.js server, but I keep encountering an error message along with another issue in the console. https://i.stack.imgur.com/Bj4M6.png Despite e ...

Tips for arranging images in a horizontal layout using FlatList in React Native

Is there a way to display feed images horizontally instead of vertically in FlatList? I've tried wrapping the images in a view with flex-direction set to row, as well as adding horizontal={true} to the FlatList, but nothing seems to work. Any suggesti ...

Retrieving information from an Object within a JSON response

After calling my JSON, I receive a specific set of arrays of objects that contain valuable data. I am currently struggling to access this data and display it in a dropdown menu. When I log the response in the console, it appears as shown in this image: htt ...

Issue with Material-UI Nested Checkbox causing parent DOM to not update upon selection changes

Currently, I am integrating a nested checkbox feature from a working example into my application. The functionality of the checkboxes covers seven different scenarios: - Scenario - No children, no parent selected - Select the parent -> select both pa ...

Component template using Knockout.js and RequireJS for HTML widgets

Trying to implement the widget example for knockout from here. Unfortunately, I am having issues loading the template from an external HTML file using requirejs. ko.components.register('like-or-dislike', { template: { require: &apos ...

Tips for testing nested HTTP calls in unit tests

I am currently in the process of unit testing a function that looks like this: async fetchGreatHouseByName(name: string) { const [house] = await this.httpGetHouseByName(name); const currentLord = house.currentLord ? house.currentLord : '957'; ...

ui-grid row size set to automatically adjust using rowHeight : 'auto'

Has anyone else experienced this strange behavior with ui-grid? When I set the rowHeight to auto, each cell in the same row ends up with different heights. One of the cells contains multiline data, which seems to be causing issues for ui-grid. I've ev ...

Jade (Pug) base HTML Page: Unable to locate element: #app

My server is running on the Vibed framework and I am using the Pug preprocessor (formerly known as Jade). Below is a snippet of my page code: doctype html html head script(src="https://unpkg.com/vue") script(src="app.js") title ...