DEV Community

Anirban Mukherjee
Anirban Mukherjee

Posted on

Custom Toggle Button Vue Component

GitHub logo anirbmuk / toggle-button-vue

A toggle-button component using Vue3

This blog post aims to create a simple Toggle-Button component with Vue3, which can also be integrated with a form, via v-model.

button toggle preview

Sometimes it is important to create these UI components on your own, instead of relying on heavier UI libraries. When you do this, you get to learn a few more intricate stuff, which you may ignore while using ready-made solutions, and also, you make it light-weight by excluding features you may not even need.


The ToggleButton Component

Props:

  • options (array)
  • modelValue (string)
defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  options: {
    type: Array as PropType<KeyValue<string>[]>,
    required: true
  }
})
Enter fullscreen mode Exit fullscreen mode

Emits:

  • update:model-value (string)
defineEmits<{
  (e: 'update:model-value', value: string): void
}>()
Enter fullscreen mode Exit fullscreen mode

Let's talk about the props.
The options array is a list of key-value objects, which are displayed as buttons.

<template v-for="option of options" :key="option.value">
  <button
    type="button"
    :class="{ selected: modelValue === option.value }"
    @click="$emit('update:model-value', option.value)"
  >
    {{ option.label }}
  </button>
</template>
Enter fullscreen mode Exit fullscreen mode

The modelValue prop is an interesting one. It should be named modelValue (case-sensitive), if you want this component to have a data-binding. When a custom component has this prop, and it is bound to a v-model, the value flows into this component and is applied to the underlying model.

If you want the component to have a 2-way data-binding, you also need to define an emit called update:model-value (again, case-sensitive). You write your logic to emit this event with the new value, every time a new button is clicked.

...
@click="$emit('update:model-value', option.value)"
...
Enter fullscreen mode Exit fullscreen mode

Now that your component is ready for 2-way binding, you can use it in your application:

<ToggleButton :options="options" v-model="selected" />
...
const options = [
  {
    label: 'Male',
    value: 'M'
  },
  {
    label: 'Female',
    value: 'F'
  },
  {
    label: 'Diverse',
    value: 'D'
  }
] satisfies KeyValue<string>[]

const selected = ref<string>('F')
Enter fullscreen mode Exit fullscreen mode

That's all folks. Refer to the GitHub repo for the complete code!


Anirban Mukherjee

Top comments (0)