Skip to content

કમ્પોનન્ટ v-model (Component v-model)

મૂળભૂત વપરાશ (Basic Usage)

v-model નો ઉપયોગ કમ્પોનન્ટ પર ટુ-વે બાઈન્ડિંગ (two-way binding) કરવા માટે થઈ શકે છે.

Vue 3.4 થી શરૂ કરીને, આ હાંસલ કરવા માટેનો ભલામણ કરેલ અભિગમ defineModel() મેક્રોનો ઉપયોગ કરવાનો છે:

Child.vue
vue
<script setup>
const model = defineModel()

function update() {
  model.value++
}
</script>

<template>
  <div>પેરેન્ટ બાઉન્ડ v-model છે: {{ model }}</div>
  <button @click="update">વધારો</button>
</template>

પેરેન્ટ પછી v-model સાથે વેલ્યુ બાંધી શકે છે:

Parent.vue
template
<Child v-model="countModel" />

defineModel() દ્વારા પરત કરવામાં આવેલી વેલ્યુ એક રિફ (ref) છે. તે અન્ય કોઈપણ રિફની જેમ એક્સેસ અને મ્યુટેટ કરી શકાય છે, સિવાય કે તે પેરેન્ટ વેલ્યુ અને લોકલ વેલ્યુ વચ્ચેના ટુ-વે બાઈન્ડિંગ તરીકે કાર્ય કરે છે:

  • તેની .value પેરેન્ટ v-model દ્વારા બાઉન્ડ વેલ્યુ સાથે સિંક (synced) થયેલ છે;
  • જ્યારે તે ચાઇલ્ડ દ્વારા મ્યુટેટ કરવામાં આવે છે, ત્યારે તે પેરેન્ટ બાઉન્ડ વેલ્યુને પણ અપડેટ કરવાનું કારણ બને છે.

આનો અર્થ એ છે કે તમે આ રિફને v-model સાથે નેટિવ ઇનપુટ એલિમેન્ટ સાથે પણ બાંધી શકો છો, જે સમાન v-model વપરાશ પ્રદાન કરતી વખતે નેટિવ ઇનપુટ એલિમેન્ટ્સને લપેટવાનું (wrap) સરળ બનાવે છે:

vue
<script setup>
const model = defineModel()
</script>

<template>
  <input v-model="model" />
</template>

Playground માં તે અજમાવી જુઓ

પડદા પાછળની પ્રક્રિયા

defineModel એક સગવડતા મેક્રો (convenience macro) છે. કમ્પાઇલર તેને નીચે પ્રમાણે વિસ્તાર કરે છે:

  • modelValue નામનો પ્રોપ, જેની સાથે લોકલ રિફની વેલ્યુ સિંક થયેલ છે;
  • update:modelValue નામની ઇવેન્ટ, જે લોકલ રિફની વેલ્યુ મ્યુટેટ થાય ત્યારે એમિટ થાય છે.

આ રીતે તમે 3.4 પહેલા ઉપર બતાવેલ તે જ ચાઇલ્ડ કમ્પોનન્ટ લાગુ કરશો:

Child.vue
vue
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>

<template>
  <input
    :value="props.modelValue"
    @input="emit('update:modelValue', $event.target.value)"
  />
</template>

પછી, પેરેન્ટ કમ્પોનન્ટમાં v-model="foo" આ રીતે કમ્પાઇલ કરવામાં આવશે:

Parent.vue
template
<Child
  :modelValue="foo"
  @update:modelValue="$event => (foo = $event)"
/>

જેમ તમે જોઈ શકો છો, તે ઘણું વધારે લખાણ છે. જો કે, પડદા પાછળ શું થઈ રહ્યું છે તે સમજવું મદદરૂપ છે.

કારણ કે defineModel પ્રોપ જાહેર કરે છે, તમે તેને defineModel માં પાસ કરીને અન્ડરલાઇંગ પ્રોપના ઓપ્શન્સ જાહેર કરી શકો છો:

js
// v-model ને જરૂરી (required) બનાવવું
const model = defineModel({ required: true })

// ડિફોલ્ટ વેલ્યુ પૂરી પાડવી
const model = defineModel({ default: 0 })

WARNING

જો તમારી પાસે defineModel પ્રોપ માટે default વેલ્યુ છે અને તમે પેરેન્ટ કમ્પોનન્ટમાંથી આ પ્રોપ માટે કોઈ વેલ્યુ પ્રદાન કરતા નથી, તો તે પેરેન્ટ અને ચાઇલ્ડ કમ્પોનન્ટ્સ વચ્ચે ડિ-સિંક્રોનાઇઝેશન (de-synchronization) નું કારણ બની શકે છે. નીચેના ઉદાહરણમાં, પેરેન્ટનો myRef અનડિફાઇન્ડ (undefined) છે, પરંતુ ચાઇલ્ડનો model ૧ છે:

Child.vue
vue
<script setup>
const model = defineModel({ default: 1 })
</script>
Parent.vue
vue
<script setup>
const myRef = ref()
</script>

<template>
  <Child v-model="myRef"></Child>
</template>

સૌ પ્રથમ ચાલો જોઈએ કે નેટિવ એલિમેન્ટ પર v-model નો ઉપયોગ કેવી રીતે થાય છે:

template
<input v-model="searchText" />

પડદા પાછળ, ટેમ્પલેટ કમ્પાઇલર અમારા માટે v-model ને વધુ વિગતવાર સમકક્ષ વિસ્તારે છે. તેથી ઉપરનો કોડ નીચે મુજબ જ કામ કરે છે:

template
<input
  :value="searchText"
  @input="searchText = $event.target.value"
/>

જ્યારે કમ્પોનન્ટ પર ઉપયોગ કરવામાં આવે ત્યારે, v-model તેના બદલે આમાં વિસ્તરે છે:

template
<CustomInput
  :model-value="searchText"
  @update:model-value="newValue => searchText = newValue"
/>

આ ખરેખર કાર્ય કરવા માટે, <CustomInput> કમ્પોનન્ટે બે વસ્તુઓ કરવી આવશ્યક છે:

૧. નેટિવ <input> એલિમેન્ટના value એટ્રિબ્યુટને modelValue પ્રોપ સાથે બાંધો (bind). ૨. જ્યારે નેટિવ input ઇવેન્ટ ટ્રિગર થાય ત્યારે, નવી વેલ્યુ સાથે update:modelValue કસ્ટમ ઇવેન્ટ એમિટ કરો.

અહીં તે ક્રિયામાં છે:

CustomInput.vue
vue
<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue']
}
</script>

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

હવે v-model એ આ ઘટક સાથે સંપૂર્ણ રીતે કામ કરવું જોઈએ:

template
<CustomInput v-model="searchText" />

Playground માં તે અજમાવી જુઓ

આ કમ્પોનન્ટની અંદર v-model ને લાગુ કરવાની બીજી રીત ગેટર અને સેટર બંને સાથે રાઈટેબલ (writable) computed પ્રોપર્ટીનો ઉપયોગ કરવાની છે. get મેથડે modelValue પ્રોપર્ટી પરત કરવી જોઈએ અને set મેથડે સંબંધિત ઇવેન્ટ એમિટ કરવી જોઈએ:

CustomInput.vue
vue
<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  computed: {
    value: {
      get() {
        return this.modelValue
      },
      set(value) {
        this.$emit('update:modelValue', value)
      }
    }
  }
}
</script>

<template>
  <input v-model="value" />
</template>

v-model આર્ગ્યુમેન્ટ્સ (v-model Arguments)

કમ્પોનન્ટ પરનું v-model આર્ગ્યુમેન્ટ પણ સ્વીકારી શકે છે:

template
<MyComponent v-model:title="bookTitle" />

ચાઇલ્ડ કમ્પોનન્ટમાં, આપણે તેની પ્રથમ આર્ગ્યુમેન્ટ તરીકે defineModel() માં સ્ટ્રિંગ પાસ કરીને સંબંધિત આર્ગ્યુમેન્ટને સપોર્ટ કરી શકીએ છીએ:

MyComponent.vue
vue
<script setup>
const title = defineModel('title')
</script>

<template>
  <input type="text" v-model="title" />
</template>

Playground માં તે અજમાવી જુઓ

જો પ્રોપ ઓપ્શન્સની પણ જરૂર હોય, તો તે મોડેલ નામ પછી પાસ કરવા જોઈએ:

js
const title = defineModel('title', { required: true })
3.4 પહેલાનો વપરાશ
MyComponent.vue
vue
<script setup>
defineProps({
  title: {
    required: true
  }
})
defineEmits(['update:title'])
</script>

<template>
  <input
    type="text"
    :value="title"
    @input="$emit('update:title', $event.target.value)"
  />
</template>

Playground માં તે અજમાવી જુઓ

આ કિસ્સામાં, ડિફોલ્ટ modelValue પ્રોપ અને update:modelValue ઇવેન્ટને બદલે, ચાઇલ્ડ કમ્પોનન્ટે title પ્રોપની અપેક્ષા રાખવી જોઈએ અને પેરેન્ટ વેલ્યુને અપડેટ કરવા માટે update:title ઇવેન્ટ એમિટ કરવી જોઈએ:

MyComponent.vue
vue
<script>
export default {
  props: ['title'],
  emits: ['update:title']
}
</script>

<template>
  <input
    type="text"
    :value="title"
    @input="$emit('update:title', $event.target.value)"
  />
</template>

Playground માં તે અજમાવી જુઓ

બહુવિધ v-model બાઈન્ડિંગ્સ (Multiple v-model Bindings)

ચોક્કસ પ્રોપ અને ઇવેન્ટને લક્ષ્ય બનાવવાની ક્ષમતાનો લાભ લઈને આપણે અગાઉ v-model આર્ગ્યુમેન્ટ્સ સાથે શીખ્યા હતા, હવે આપણે સિંગલ કમ્પોનન્ટ ઇન્સ્ટન્સ પર બહુવિધ v-model બાઈન્ડિંગ્સ બનાવી શકીએ છીએ.

દરેક v-model કમ્પોનન્ટમાં વધારાના ઓપ્શન્સની જરૂરિયાત વિના, અલગ પ્રોપ સાથે સિંક થશે:

template
<UserName
  v-model:first-name="first"
  v-model:last-name="last"
/>
vue
<script setup>
const firstName = defineModel('firstName')
const lastName = defineModel('lastName')
</script>

<template>
  <input type="text" v-model="firstName" />
  <input type="text" v-model="lastName" />
</template>

Playground માં તે અજમાવી જુઓ

3.4 પહેલાનો વપરાશ
vue
<script setup>
defineProps({
  firstName: String,
  lastName: String
})

defineEmits(['update:firstName', 'update:lastName'])
</script>

<template>
  <input
    type="text"
    :value="firstName"
    @input="$emit('update:firstName', $event.target.value)"
  />
  <input
    type="text"
    :value="lastName"
    @input="$emit('update:lastName', $event.target.value)"
  />
</template>

Playground માં તે અજમાવી જુઓ

vue
<script>
export default {
  props: {
    firstName: String,
    lastName: String
  },
  emits: ['update:firstName', 'update:lastName']
}
</script>

<template>
  <input
    type="text"
    :value="firstName"
    @input="$emit('update:firstName', $event.target.value)"
  />
  <input
    type="text"
    :value="lastName"
    @input="$emit('update:lastName', $event.target.value)"
  />
</template>

Playground માં તે અજમાવી જુઓ

v-model મોડિફાયર્સ ને હેન્ડલ કરવા (Handling v-model Modifiers)

જ્યારે આપણે ઇનપુટ બાઇન્ડિંગ્સ ફોર્મ (form input bindings) શીખી રહ્યા હતા, ત્યારે આપણે જોયું કે v-model માં બિલ્ટ-ઇન મોડિફાયર્સ છે - .trim, .number અને .lazy. કેટલાક કિસ્સાઓમાં, તમે કસ્ટમ મોડિફાયર્સને સપોર્ટ કરવા માટે તમારા કસ્ટમ ઇનપુટ કમ્પોનન્ટ પર v-model પણ ઈચ્છી શકો છો.

ચાલો એક ઉદાહરણ કસ્ટમ મોડિફાયર, capitalize બનાવીએ, જે v-model બાઇન્ડિંગ દ્વારા પૂરી પાડવામાં આવેલ સ્ટ્રિંગના પ્રથમ અક્ષરને કેપિટલાઇઝ (મોટો) કરે છે:

template
<MyComponent v-model.capitalize="myText" />

કમ્પોનન્ટ v-model માં ઉમેરવામાં આવેલા મોડિફાયર્સને આ રીતે defineModel() રિટર્ન વેલ્યુને ડિસ્ટ્રક્ચર કરીને ચાઇલ્ડ કમ્પોનન્ટમાં એક્સેસ કરી શકાય છે:

vue
<script setup>
const [model, modifiers] = defineModel()

console.log(modifiers) // { capitalize: true }
</script>

<template>
  <input type="text" v-model="model" />
</template>

મોડિફાયર્સના આધારે વેલ્યુ કેવી રીતે વાંચવી/લખવી જોઈએ તે શરતી રીતે ગોઠવવા માટે, અમે defineModel() માં get અને set ઓપ્શન્સ પાસ કરી શકીએ છીએ. આ બે ઓપ્શન્સ મોડલ રિફ ના ગેટ/સેટ (get / set) પર વેલ્યુ મેળવે છે અને ટ્રાન્સફોર્મ કરેલી વેલ્યુ પરત કરવી જોઈએ. આ રીતે આપણે capitalize મોડિફાયરને લાગુ કરવા માટે set ઓપ્શનનો ઉપયોગ કરી શકીએ છીએ:

vue
<script setup>
const [model, modifiers] = defineModel({
  set(value) {
    if (modifiers.capitalize) {
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
    return value
  }
})
</script>

<template>
  <input type="text" v-model="model" />
</template>

Playground માં તે અજમાવી જુઓ

3.4 પહેલાનો વપરાશ
vue
<script setup>
const props = defineProps({
  modelValue: String,
  modelModifiers: { default: () => ({}) }
})

const emit = defineEmits(['update:modelValue'])

function emitValue(e) {
  let value = e.target.value
  if (props.modelModifiers.capitalize) {
    value = value.charAt(0).toUpperCase() + value.slice(1)
  }
  emit('update:modelValue', value)
}
</script>

<template>
  <input type="text" :value="props.modelValue" @input="emitValue" />
</template>

Playground માં તે અજમાવી જુઓ

કમ્પોનન્ટ v-model માં ઉમેરવામાં આવેલા મોડિફાયર્સ modelModifiers પ્રોપ દ્વારા કમ્પોનન્ટ ને પૂરા પાડવામાં આવશે. નીચેના ઉદાહરણમાં, અમે એક કમ્પોનન્ટ બનાવ્યું છે જેમાં modelModifiers પ્રોપ છે જે ડિફોલ્ટ રૂપે ખાલી ઓબ્જેક્ટ છે:

vue
<script>
export default {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:modelValue'],
  created() {
    console.log(this.modelModifiers) // { capitalize: true }
  }
}
</script>

<template>
  <input
    type="text"
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

નોંધ કરો કે કમ્પોનન્ટના modelModifiers પ્રોપમાં capitalize છે અને તેનું મૂલ્ય true છે - તે v-model બાઇન્ડિંગ v-model.capitalize="myText" પર સેટ કરવામાં આવ્યું હોવાને કારણે.

હવે જ્યારે અમારી પાસે અમારો પ્રોપ સેટઅપ છે, અમે modelModifiers ઓબ્જેક્ટ કીઝને ચેક કરી શકીએ છીએ અને એમિટ થયેલી વેલ્યુ ને બદલવા માટે હેન્ડલર લખી શકીએ છીએ. નીચેના કોડમાં જ્યારે પણ <input /> એલિમેન્ટ input ઇવેન્ટને ફાયર કરશે ત્યારે અમે સ્ટ્રિંગને કેપિટલાઇઝ (પ્રથમ અક્ષર મોટો) કરીશું.

vue
<script>
export default {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:modelValue'],
  methods: {
    emitValue(e) {
      let value = e.target.value
      if (this.modelModifiers.capitalize) {
        value = value.charAt(0).toUpperCase() + value.slice(1)
      }
      this.$emit('update:modelValue', value)
    }
  }
}
</script>

<template>
  <input type="text" :value="modelValue" @input="emitValue" />
</template>

Playground માં તે અજમાવી જુઓ

આર્ગ્યુમેન્ટ્સ સાથે v-model માટે મોડિફાયર્સ

આર્ગ્યુમેન્ટ અને મોડિફાયર બંને સાથે v-model બાઈન્ડિંગ્સ માટે, જનરેટ થયેલ પ્રોપ નામ arg + "Modifiers" હશે. ઉદાહરણ તરીકે:

template
<MyComponent v-model:title.capitalize="myText">

તેના માટેની ડિક્લેરેશન્સ નીચે મુજબ હોવી જોઈએ:

js
export default {
  props: ['title', 'titleModifiers'],
  emits: ['update:title'],
  created() {
    console.log(this.titleModifiers) // { capitalize: true }
  }
}

અહીં વિવિધ આર્ગ્યુમેન્ટ્સ સાથે બહુવિધ (multiple) v-model સાથે મોડિફાયર્સ વાપરવાનું બીજું ઉદાહરણ છે:

template
<UserName
  v-model:first-name.capitalize="first"
  v-model:last-name.uppercase="last"
/>
vue
<script setup>
const [firstName, firstNameModifiers] = defineModel('firstName')
const [lastName, lastNameModifiers] = defineModel('lastName')

console.log(firstNameModifiers) // { capitalize: true }
console.log(lastNameModifiers) // { uppercase: true }
</script>
3.4 પહેલાનો વપરાશ
vue
<script setup>
const props = defineProps({
  firstName: String,
  lastName: String,
  firstNameModifiers: { default: () => ({}) },
  lastNameModifiers: { default: () => ({}) }
})
defineEmits(['update:firstName', 'update:lastName'])

console.log(props.firstNameModifiers) // { capitalize: true }
console.log(props.lastNameModifiers) // { uppercase: true }
</script>
vue
<script>
export default {
  props: {
    firstName: String,
    lastName: String,
    firstNameModifiers: {
      default: () => ({})
    },
    lastNameModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:firstName', 'update:lastName'],
  created() {
    console.log(this.firstNameModifiers) // { capitalize: true }
    console.log(this.lastNameModifiers) // { uppercase: true }
  }
}
</script>
કમ્પોનન્ટ v-model (Component v-model) has loaded