DEV Community

Ahamed Rasni Nathees
Ahamed Rasni Nathees

Posted on

Creating a Custom Input Component with v-model Binding in Vue 3

When building a Vue 3 application, managing form inputs through components is a common practice. One of the powerful features of Vue is the v-model directive, which simplifies two-way data binding. In this blog post, we will explore how to create a custom input component and use v-model to bind its value in a parent component.

1. Understanding v-model in Vue 3

In Vue 3, v-model is a shorthand for creating two-way data bindings on form input elements. The directive binds the value of the input to a data property and listens for changes to update the property.

<input v-model="password" />
Enter fullscreen mode Exit fullscreen mode

In the above example, the password data property is bound to the input value. When the input value changes, the password property updates automatically.

2. Creating the Custom Input Component

Let's say we want to create a reusable input component called BaseInputGroup. Here's how the component might look:

<template>
  <div class="flex flex-col text-white mx-5 md:mx-0 space-y-2 mb-2">
    <label :for="labelFor">
      {{ labelFor.toLocaleUpperCase() }}
    </label>
    <input
      :type="type"
      :name="name"
      @input="$updateInputValue"
      :value="modelValue"
      class="p-2 px-4 rounded-2xl bg-white/15 focus:outline-none focus:ring focus:border-blue-500"
    />
  </div>
</template>

<script setup lang="ts">
import { defineProps, defineOptions, defineEmits } from 'vue'

defineOptions({
  inheritAttrs: false
})

defineProps({
  labelFor: {
    type: String,
    required: true
  },
  name: {
    type: String,
    required: true
  },
  type: {
    type: String,
    default: 'text'
  },
  modelValue: {
    type: [String, Number],
    default: ''
  }
})

// Emit an event to update the v-model in the parent component
const emit = defineEmits(['update:modelValue'])
const $updateInputValue = (event: Event) => {
  const input = event.target as HTMLInputElement
  emit('update:modelValue', input.value)
}
</script>
Enter fullscreen mode Exit fullscreen mode

3. Binding v-model in the Parent Component

To use this component in a parent component with v-model, you simply bind the model to a data property in the parent component. Here's an example:

<template>
  <BaseInputGroup
    labelFor="password"
    name="password"
    type="password"
    v-model="password"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import BaseInputGroup from './components/BaseInputGroup.vue'

const password = ref('')
</script>
Enter fullscreen mode Exit fullscreen mode

4. How It Works

Model Value Prop: The modelValue prop represents the value of the input. It's passed from the parent component via v-model.

Emitting the Update: The $updateInputValue function listens for input events and emits an update:modelValue event with the new input value. This updates the parent component's password value.

Binding in the Parent: In the parent component, the v-model directive binds to the password data property, ensuring that the value is always in sync with the custom input component.

5. Benefits of Using Custom Components with v-model

Reusability: The custom input component can be reused across your application, reducing code duplication.

Separation of Concerns: The logic for handling input values is encapsulated within the component, making the parent component cleaner and more focused on its core functionality.

Customization: You can easily extend the custom input component to include additional features, like validation, different input types, or custom styles, without affecting the parent component.

Conclusion

Using v-model with custom components in Vue 3 is a powerful way to manage form inputs and data binding. By emitting the update:modelValue event, you can ensure that your components remain in sync with the parent component's data properties, making your code more modular, maintainable, and easier to understand.

This pattern is especially useful in larger applications where input handling logic can become complex and repetitive. By leveraging Vue 3's composition API and the v-model directive, you can create flexible and reusable components that simplify your codebase.

Top comments (0)