DEV Community

Cover image for Vue3 Tailwind CSS Form Components Part II - Reusable BaseTextarea Component
ScriptMint
ScriptMint

Posted on

Vue3 Tailwind CSS Form Components Part II - Reusable BaseTextarea Component

This is second part of Vue3 Tailwind Form Components Series

Form Components are very important for any Web Application. Think about a project without proper Form Components with multiple forms in it. What if you need to change design of your text input or you wish to add extra functionality into text input? I did the same mistake in 2018 when using Vue2 and still my project is not easy to maintain.

Live Demo: https://scriptmint-solution.github.io/vue3-tailwind-form-components/

GitHub Repository: https://github.com/scriptmint-solution/vue3-tailwind-form-components

Do check our Advanced Featured Admin Panel at Vana Admin built with Laravel, Vue.js 3 & Tailwind CSS 3 with tons of inbuilt features to quickly build your next project.

BaseTextarea

Lets start with this Component:

BaseTextarea will be very similar to BaseInput. BaseInput accepts single line of text input while BaseTextarea will accept multi line text input.

<BaseTextarea id="name" name="name" label="Sample Textarea" />
Enter fullscreen mode Exit fullscreen mode

Here is the output we are expecting:

image.png

Lets start with a very basic textarea component. Create a BaseTextarea.vue file inside your components directory.

<template>
    <div>
        <textarea
            rows="3" class="w-full shadow appearance-none border rounded py-2 px-3 
            text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
        />
    </div>
</template>

<script>
export default {
    name: 'BaseTextarea',
    inheritAttrs: false
}
</script>

<script setup>
</script>
Enter fullscreen mode Exit fullscreen mode

We have only applied some css classes to make it look better and a row attribute. Lets add some props now. Also note that we have set inheriAttrs property to false, as we wish to bind the attributes of BaseTextarea to the input field (Not with the root element).

<script setup>
const props = defineProps({
    label: {
        type: String,
        default: ''
    },
    placeholder: {
        type: String,
        default: ''
    },
    modelValue: {
        type: [String, Number],
        default: ''
    }
})
</script>
Enter fullscreen mode Exit fullscreen mode

In Vue3, you can pass v-model attribute in your component and it will be available as modelValue inside your component. Also, we need to bind this modelValue to the value attribute of the input field.

Next, we need to emit the value everytime whenever user input a value. To do so, we will make

<textarea
    v-bind="$attrs"
    rows="3" class="w-full shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
    :value="modelValue"
    @input="updateInput"
/>
...
...

const emit = defineEmits(['update:modelValue'])

const updateInput = ($event) => {
    emit('update:modelValue', $event.target.value)
}
Enter fullscreen mode Exit fullscreen mode

Here, we bind the attributes to the the field which emits the value of the textarea field and make it available to the BaseTextarea component v-model attribute via two way binding.

That's it. You have successfully created your BaseTextarea component and use it anywhere in the project.

Let's assume you need to add another functionality to add labels above your input field. You don't need to go every single textarea field but edit it only in the BaseTextarea component field.

Remember we created BaseLabel component in the last article. Lets use it in your BaseTextarea component as below:

<BaseLabel :for="$attrs.id">{{label}}</BaseLabel>

...
...
Enter fullscreen mode Exit fullscreen mode
<script setup>
import BaseLabel from  './BaseLabel.vue'

....
....
Enter fullscreen mode Exit fullscreen mode

Similarly, you can help block or error message component and add it in your BaseTextarea field.

Check all the source code in the GitHub repo at https://github.com/scriptmint-solution/vue3-tailwind-form-components

Discussion (0)