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

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more