DEV Community

Cover image for Vue3 Tailwind Form Components Part IV - Reusable BaseRadio Component
ScriptMint
ScriptMint

Posted on

Vue3 Tailwind Form Components Part IV - Reusable BaseRadio Component

This is fourth article 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 radio input or you wish to add extra functionality into radio 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.

BaseRadio

Building BaseRadio component is little complex. Let's build together.

We will start with a basic radio input.

<template>
    <div class="flex items-center">
        <input
            type="radio"
            class="focus:ring-0 h-4 w-4"
        />
        <label class="ml-2 block text-sm text-gray-900">
            label goes here!
        </label>
    </div>
</template>

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

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

I hope you understand the meaning of inheritAttrs by now. If not, please refer to our previous articles of this series.

Above we created a simple radio button and a label for its description. Each radio button should have an option and similar to checkbox input, it can be checked. So let's modify this component to accept value and add change event on it.

<input
    v-bind="$attrs"
    :checked="modelValue === value"
    @change="updateInput"
    :value="value"
    type="radio"
    class="focus:ring-0 h-4 w-4"
/>
<label class="ml-2 block text-sm text-gray-900">
    {{label}}
</label>

...
...

<script setup>
const emit = defineEmits(['update:modelValue'])

const props = defineProps({
    label: {
        type: String,
        default: ''
    },
    modelValue: {
        type: [String, Number],
        default: ''
    },
    value: {
        type: [String, Number],
        required: true,
    }
})

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

Here, we are passing three props to the component. We also bind the value of the radio input to the value property. To check whether the radio input will be selected or not, we have compared the modelValue with the given value.

At the change event of radio input, we will emit an event to the component with the value.

So, we have done with the BaseRadio component. What next?

Radio Inputs are always used for multiple options. You never use it for single option (Checkbox is available for this purpose)

So how can we generate BaseRadio component for multiple options? We will create another component BaseRadioGroup. Let's see how!

Create BaseRadioGroup.vue file in the components folder.

<template>
    <div class="flex space-x-4">
        <BaseRadio
            v-for="option in options"
            :label="option.label"
            :value="option.value"
            :name="name"
            v-model="modelValue"
            @update:modelValue="updateInput"
        />
    </div>
</template>

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

<script setup>
import BaseRadio from './BaseRadio.vue'
const emit = defineEmits(['update:modelValue'])

const props = defineProps({
    options: {
        type: Array,
        required: true
    },
    name: {
        type: String,
        required: true
    },
    modelValue: {
        type: [String, Number],
        required: true
    }
})

const updateInput = ($event) => {
    emit('update:modelValue', $event)
}
</script>
Enter fullscreen mode Exit fullscreen mode

In this component, we are passing three properties: An array of options, name for the radio input & model value (i.e. v-model)

We are looping through the options and generating BaseRadio component for each option by passing label & value attribute. Also we are binding v-model to the given modelValue (Used to pre-select option).

We are also listening to update:modelValue event and emiting event to its parent component.

So we have completed our BaseRadio & BaseRadioGroup component. Let's see how can we use it.

<BaseRadioGroup
    :options="[
        {label: 'Option 1', value: 'option1'},
        {label: 'Option 2', value: 'option2'},
    ]"
    name="option"
    v-model="sampleRadio"
/>
Enter fullscreen mode Exit fullscreen mode

Hope you get the idea behind this component. Checkout the full source code in the GitHub repository at https://github.com/scriptmint-solution/vue3-tailwind-form-components

Do let your feedback or suggestion to improve this component.

Discussion (0)