stevendesu
stevendesu

Reputation: 16771

How to assign `value` prop and `v-model` prop to custom Vue component?

I want to create a custom Vue component for a "radio div" -- a div (with a slot for including any content I want) that acts like a radio button so you can select it and only one can be selected among multiple with the same name.

In general radio buttons in VueJS look like so:

<input type="radio" name="name" value="value" v-model="variable" />

So I wanted a similar API:

<div-radio name="name" value="value" v-model="variable" />

However when I looked up how to add v-model support to custom component the first link I found on Google claimed:

For input elements, you might use v-model like this:

<input v-model="email" />

v-model translates to this:

<input :value="email" @input="e => email = e.target.value" />

If v-model translates to :value and @input then it doesn't seem possible to have a prop called "value" at the same time as "v-model" - despite the fact this is how normal VueJS radio buttons work

Am I misunderstanding how v-model works? Or is there an alternate solution? Or is what I want just not possible?

Upvotes: 2

Views: 4775

Answers (2)

tony19
tony19

Reputation: 138216

Vue allows configuring v-model's prop name and event name through the component's model option:

model

New in 2.2.0

Type: { prop?: string, event?: string }

Details:

Allows a custom component to customize the prop and event used when it’s used with v-model. By default, v-model on a component uses value as the prop and input as the event, but some input types such as checkboxes and radio buttons may want to use the value prop for a different purpose. Using the model option can avoid the conflict in such cases.

Example:

Vue.component('my-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    // this allows using the `value` prop for a different purpose
    value: String,
    // use `checked` as the prop which take the place of `value`
    checked: {
      type: Number,
      default: 0
    }
  },
  // ...
})
<my-checkbox v-model="foo" value="some value"></my-checkbox>

The above will be equivalent to:

<my-checkbox
  :checked="foo"
  @change="val => { foo = val }"
  value="some value">
</my-checkbox>

Upvotes: 4

Raeisi
Raeisi

Reputation: 2171

To use v-model you need to handle value and @input manually:

<template>
 <div>
  <input type="radio" :name="name" :value="value" @input="$emit('input', $event)" />
 </div
</template>

<script>
 export default {
  name: 'div-radio',
  props:{
    value: Boolean,
    name: String
  }
 }
</script>

In a host component, treat it as a normal component:

...
<div-radio name="name" v-model="variable1" />
<div-radio name="name" v-model="variable2" />
... 

Upvotes: 1

Related Questions