How to easily sync with multiple v-models in Vue 3 using Composition API
Tags: vue, javascript, programming, coding
Published: 2021-03-17 17:05:48

---
title: How to easily sync with multiple v-models in Vue 3 using Composition API
published: true
description: Vue 3 has brought many new features, and the ability to use more than one v-model directive on the same element is one of them. I want to share with you a quick tip on how to handle updating the state of a parent component when using multiple v-models. 
tags: Vue, JavaScript, Programming, Coding
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2envk5xzh4qf9vkebex.png
---

This article was originally published at [The Road To Enterprise](https://theroadtoenterprise.com/blog/how-to-easily-sync-with-multiple-v-models-in-vue-3-using-composition-api).

---

Vue 3 has brought many new features, and the ability to use more than one v-model directive on the same element is one of them. I want to share with you a quick tip on how to handle updating the state of a parent component when using multiple v-models. It's especially useful when dealing with forms. You can find the full code example in this [GitHub repository](https://github.com/ThomasFindlay/handle-multiple-vmodels-using-composition-api).

For this example, we will use a form shown in the image below.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vqr9ne1qih3fl3yu4u3c.png)

Below you can find the code for it. We have two files - `App.vue`, which has the form state and renders the `Form` component. The `Form.vue` component renders the form element with labels and inputs fields.

**App.vue**

```vue
<template>
  <div :class="$style.container">
    <Form
      v-model:name="form.name"
      v-model:surname="form.surname"
      @submit="onSubmit"
    />
  </div>
</template>

<script>
import { ref } from 'vue'
import Form from './components/Form.vue'

export default {
  components: {
    Form,
  },
  setup() {
    const form = ref({
      name: '',
      surname: '',
    })

    const onSubmit = () => console.log(form)

    return {
      form,
      onSubmit,
    }
  },
}
</script>

<style module>
.container {
  max-width: 30rem;
  @apply mx-auto py-8;
}
</style>
```

**components/Form.vue**

```vue
<template>
  <form @submit.prevent="$emit('submit')">
    <div :class="$style.formBlock">
      <label :class="$style.label">Name</label>
      <input
        v-model="nameState"
        :class="$style.input"
        type="text"
        aria-label="Name input"
      />
    </div>
    <div :class="$style.formBlock">
      <label :class="$style.label">Surname</label>
      <input
        v-model="surnameState"
        :class="$style.input"
        type="text"
        aria-label="Surname input"
      />
    </div>
    <div>
      <button
        class="float-right bg-blue-100 text-blue-900 px-4 py-3 rounded font-semibold"
        type="submit"
      >
        Submit
      </button>
    </div>
  </form>
</template>

<script>
import { useVModel } from '../composables/useVModel.js'
export default {
  emits: ['update:name', 'update:surname', 'submit'],
  props: {
    name: String,
    surname: String,
  },
  setup(props) {
    return {
      nameState: useVModel(props, 'name'),
      surnameState: useVModel(props, 'surname'),
    }
  },
}
</script>

<style module>
.formBlock {
  @apply flex flex-col mb-4;
}
.label {
  @apply mb-2;
}
.input {
  @apply px-4 py-3 shadow rounded border border-gray-300 bg-white;
}
</style>
```

To update the state in the parent, we need to emit an `update:<modelValue>` event.

Here is the code for the `useVModel` helper.

**composables/useVModel.js**

```javascript
import { computed, getCurrentInstance } from 'vue'

export const useVModel = (props, propName) => {
  const vm = getCurrentInstance().proxy

  return computed({
    get() {
      return props[propName]
    },
    set(value) {
      vm.$emit(`update:${propName}`, value)
    },
  })
}
```

We have to pass the `props` object to keep the reactivity intact and the prop name which we want to sync with. Inside of the `useVModel` we get access to the current instance via `getCurrentInstance()`, as we need access to the `$emit` method. The `computed` receives an object with a getter and setter. The getter returns the value passed via props, whilst the setter emits an event to update the value. Thanks to this little helper, keeping the state passed through props via v-models is much cleaner and simpler.

I hope you enjoyed this article. If you would like to learn more tips, advanced patterns, techniques and best practices related to Vue, you might want to check out ["Vue - The Road To Enterprise"](https://theroadtoenterprise.com/?utm_source=theroadtoenterprise_blog&utm_medium=article_learn_more&utm_campaign=vue_the_road_to_enterprise) book and subscribe to the [newsletter](https://theroadtoenterprise.com/blog).