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="countModel" />

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

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

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

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

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

চেষ্টা করুন

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 })

WARNING

যদি আপনার কাছে defineModel প্রপের জন্য একটি default মান থাকে এবং আপনি এই প্রপের জন্য অভিভাবক কম্পোনেন্ট থেকে কোনো মান প্রদান না করেন, তাহলে এটি পিতামাতা এবং শিশু কম্পোনেন্টগুলির মধ্যে একটি ডি-সিঙ্ক্রোনাইজেশন সৃষ্টি করতে পারে। নীচের উদাহরণে, পিতামাতার myRef অসংজ্ঞায়িত, কিন্তু সন্তানের model হল 1:

js
// child component:
const model = defineModel({ default: 1 })

// parent component:
const myRef = ref()
html
<Child v-model="myRef"></Child>

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

  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: {
    required: true
  }
})
defineEmits(['update:title'])
</script>

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

চেষ্টা করুন

এই ক্ষেত্রে, ডিফল্ট modelValue প্রপ এবং update:modelValue ইভেন্টের পরিবর্তে, চাইল্ড কম্পোনেন্টের একটি title প্রপ আশা করা উচিত এবং প্যারেন্ট মান আপডেট করার জন্য একটি update:title ইভেন্ট নির্গত করা উচিত:

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>

চেষ্টা করুন

একটি 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>

চেষ্টা করুন

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