Skip to content

Component v-model

Basic Usage

টু-ওয়ে বাইন্ডিং বাস্তবায়ন করতে একটি উপাদানে v-model ব্যবহার করা যেতে পারে।

Vue ৩.৪ থেকে শুরু করে, এটি অর্জন করার জন্য প্রস্তাবিত পদ্ধতি হল defineModel() ম্যাক্রো ব্যবহার করা:

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

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

<template>
  <div>parent bound v-model is: {{ model }}</div>
</template>

প্যারেন্ট তারপর v-মডেল দিয়ে একটি মান আবদ্ধ করতে পারেন:

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

defineModel() দ্বারা প্রত্যাবর্তিত মানটি একটি রেফ। এটি অন্য যেকোন রেফের মতো অ্যাক্সেস এবং পরিবর্তন করা যেতে পারে, এটি ব্যতীত এটি একটি অভিভাবক মান এবং স্থানীয় একটির মধ্যে দ্বি-মুখী বাঁধাই হিসাবে কাজ করে:

  • এর .value প্যারেন্ট v-model দ্বারা আবদ্ধ মানের সাথে সিঙ্ক করা হয়েছে;
  • যখন এটি সন্তানের দ্বারা পরিবর্তিত হয়, তখন এটি পিতামাতার আবদ্ধ মানটিকেও আপডেট করে।

এর মানে হল আপনি এই রেফটিকে একটি নেটিভ ইনপুট উপাদানের সাথে v-model এর সাথে আবদ্ধ করতে পারেন, একই v-model ব্যবহার প্রদান করার সময় নেটিভ ইনপুট উপাদানগুলিকে মোড়ানো সহজ করে তোলে:

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

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

Playground Example

Under the Hood

defineModel একটি সুবিধাজনক ম্যাক্রো। কম্পাইলার এটিকে নিম্নলিখিতগুলিতে প্রসারিত করে:

  • modelValue নামের একটি প্রপ, যার সাথে স্থানীয় রেফের মান সিঙ্ক করা হয়;
  • update:modelValue নামের একটি ইভেন্ট, যা স্থানীয় রেফের মান পরিবর্তন করা হলে নির্গত হয়।

এইভাবে আপনি ৩.৪ এর আগে উপরে দেখানো একই শিশু উপাদানটি বাস্তবায়ন করবেন:

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>

আপনি দেখতে পাচ্ছেন, এটি বেশ কিছুটা বেশি শব্দসমৃদ্ধ। যাইহোক, হুডের নীচে কী ঘটছে তা বোঝার জন্য এটি সহায়ক।

যেহেতু defineModel একটি প্রপ ঘোষণা করে, তাই আপনি defineModel-এ পাস করে অন্তর্নিহিত প্রপের বিকল্পগুলি ঘোষণা করতে পারেন:

js
// making the v-model required
const model = defineModel({ required: true })

// providing a default value
const model = defineModel({ default: 0 })

First let's revisit how v-model is used on a native element:

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> কম্পোনেন্টটিকে অবশ্যই দুটি জিনিস করতে হবে:

  1. একটি নেটিভ <input> কম্পোনেন্টের value বৈশিষ্ট্যকে modelValue প্রপের সাথে আবদ্ধ করুন
  2. যখন একটি নেটিভ input ইভেন্ট ট্রিগার হয়, তখন নতুন মান সহ একটি update:modelValue কাস্টম ইভেন্ট নির্গত করুন

এখানে এটি কর্মে রয়েছে:

vue
<!-- CustomInput.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" />

চেষ্টা করুন

এই উপাদানের মধ্যে v-মডেল বাস্তবায়নের আরেকটি উপায় হল একটি লিখনযোগ্য computed বৈশিষ্ট্য একটি গেটার এবং একটি সেটারের সাথে ব্যবহার করা। get পদ্ধতিটি modelValue বৈশিষ্ট্য প্রদান করবে এবং set পদ্ধতিটি সংশ্লিষ্ট ইভেন্ট নির্গত করবে:

vue
<!-- CustomInput.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 arguments

একটি উপাদানে v-model একটি যুক্তিও গ্রহণ করতে পারে:

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

চাইল্ড কম্পোনেন্টে, আমরা এর প্রথম আর্গুমেন্ট হিসাবে defineModel()-এ একটি স্ট্রিং পাস করে সংশ্লিষ্ট আর্গুমেন্টকে সমর্থন করতে পারি:

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

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

চেষ্টা করুন

যদি প্রপ বিকল্পগুলিরও প্রয়োজন হয়, সেগুলি মডেলের নামের পরে পাস করা উচিত:

js
const title = defineModel('title', { required: true })
৩.৪ এর পূর্বের ব্যবহার
vue
<!-- MyComponent.vue -->
<script setup>
defineProps(['title'])
defineEmits(['update:title'])
</script>

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

চেষ্টা করুন

In this case, instead of the default modelValue prop and update:modelValue event, the child component should expect a title prop and emit an update:title event to update the parent value:

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

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

চেষ্টা করুন

Multiple v-model bindings

v-model arguments দিয়ে আমরা আগে যেমন শিখেছি তেমন কোনো নির্দিষ্ট প্রপ এবং ইভেন্টকে টার্গেট করার ক্ষমতাকে কাজে লাগিয়ে, আমরা এখন একটি একক কম্পোনেন্ট ইনস্ট্যান্সে একাধিক 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>

চেষ্টা করুন

৩.৪ এর পূর্বের ব্যবহার
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>

চেষ্টা করুন

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>

চেষ্টা করুন

Handling v-model modifiers

আমরা যখন ফর্ম ইনপুট বাইন্ডিং সম্পর্কে শিখছিলাম, তখন আমরা দেখেছিলাম যে 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>

মডিফায়ারের উপর ভিত্তি করে মান কীভাবে পড়া/লিখতে হবে তা শর্তসাপেক্ষে সামঞ্জস্য করতে, আমরা get এবং set বিকল্পগুলিকে defineModel()-এ পাস করতে পারি। এই দুটি বিকল্প মডেল রেফের গেট/সেটের মান পায় এবং একটি রূপান্তরিত মান ফেরত দেয়। এইভাবে আমরা 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>

চেষ্টা করুন

৩.৪ এর পূর্বের ব্যবহার
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="modelValue" @input="emitValue" />
</template>

চেষ্টা করুন

Los modificadores agregados a un componente v-model se proporcionarán al componente a través de la propiedad modelModifiers. En el siguiente ejemplo, hemos creado un componente que contiene un accesorio modelModifiers que por defecto es un objeto vacío:

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>

চেষ্টা করুন

Modifiers for v-model with arguments

আর্গুমেন্ট এবং মডিফায়ার উভয়ের সাথে 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 }
  }
}

এখানে বিভিন্ন আর্গুমেন্ট সহ একাধিক 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>
৩.৪ এর পূর্বের ব্যবহার
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>
Component v-model has loaded