Vue two way data-binding in custom checkbox
Tags: vue, components, data, binding
Published: 2021-06-08 23:29:41

---
title: Vue two way data-binding in custom checkbox
published: true
description: Learn how to implement two way data binding in Vue, to create a custom checkbox component.
tags: vue, components, data, binding
//cover_image: https://direct_url_to_image.jpg
---

When writing vue application, you'll probably come across a situation where you need to write custom input components, and therefore leverage the two way data binding functionality.

A simple custom text input is easiy achievable and it's [documented here](https://vuejs.org/v2/guide/components.html#Using-v-model-on-Components)

But there's a different approach to achieve the same two way data binding functionality in custom checkbox components.

## Creating the custom checkbox component

Let's start creating our component. It will be as simple as just rendering the checkbox and a label can be set through props.


**Checkbox.vue**
```vue
<template>
	<label>
		<input  type="checkbox" :value="inputValue"  v-model="model" />
		<span>{{ label }}</span>
	</label>
</template>

<script>
export default {
  name: "Checkbox",
  props: {
    label: String,
    value: Array,
    inputValue: String,
  },
  computed: {
    model: {
      get() {
        return this.value;
      },
      set(value) {
        this.$emit("input", value);
      },
    },
  },
};
</script>
```

Now, take a look at this part:

```vue
<input  type="checkbox" :value="inputValue"  v-model="model" />
```

We are defining a checkbox input, and binding the `value` attribute to our `inputValue`, which will simply be used to determine the input's value for a form submission for example, just like you would do with normal html

```html
<input  type="checkbox" value="somoething" />
```



Now, `v-model` is bound to a property called `model` which is a **computed** property:

```javascript
computed: {
    model: {
      get() {
        return this.value;
      },
      set(value) {
        this.$emit("input", value);
      },
    },
  },
```

The getter for this property will simply return value to `v-model` and when the data has to be updated, through the setter, we emit the input event, to let the part of the application that's using this custom checkbox component, that the value has been updated.

It's important to note that the `value` property was declared as being an array, since each time we mark a new checkbox, this checkbox value will be pushed to this array bound to `v-model` property.



## Using the component

Now that we have defined how our component will work, we can use it in an example and see if it wil work.

I'll just define a simple Vue component that will use this checkbox component we just created:



**Home.vue**

```vue
<template>
  <div>
    <Checkbox label="React" inputValue="react" v-model="selectedOptions" />
    <Checkbox label="Vue" inputValue="vue" v-model="selectedOptions" />
    <Checkbox label="Angular" inputValue="angular" v-model="selectedOptions" />

    <br /><br /><br />

    <ul>
      <li v-for="(option, index) of selectedOptions" :key="index">
        {{ option }}
      </li>
    </ul>
  </div>
</template>

<script>
import Checkbox from "./Checkbox";

export default {
  name: "Home",
  props: {},
  components: {
    Checkbox,
  },
  data() {
    return {
      selectedOptions: [],
    };
  },
};
</script>
```



In this example, we have three checkboxes component in use, with three different value for each one of them: `react, vue and angular` with their respective labels.

```vue
    <Checkbox label="React" inputValue="react" v-model="selectedOptions" />
    <Checkbox label="Vue" inputValue="vue" v-model="selectedOptions" />
    <Checkbox label="Angular" inputValue="angular" v-model="selectedOptions" />
```



We are binding the `v-model` property to `selectedOptions` reactive data property of our home component, which wil be an array.

To make sure that we are updating this `selectedOptions` each time a check or uncheck an input, I added a simple loop, to render each value in `selectedOptions` array:

```vue
<ul>
    <li v-for="(option, index) of selectedOptions" :key="index">
        {{ option }}
    </li>
</ul>
```

**Nothing selected:**
![Nothing selected](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/guao86chmdgmetpdc9yc.png)

**All selected:**
![All selected](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hs4rbyd346kircmtzg75.png)

**Two selected:**
![Two selected](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dyd88269xdayedh6ktj8.png)

You can see a working example here in CodeSandbox:

[![Edit dreamy-sea-0467f](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/dreamy-sea-0467f?fontsize=14&hidenavigation=1&theme=dark)