new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Vue · Tutorial · all subjects

form binding

29 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

defineModel macro for v-model binding

The `defineModel()` macro is available in Vue 3.4+ and declares a two-way binding prop that can be consumed via `v-model` from the parent component. If the first argument is a literal string, it will be used as the prop name; otherwise the prop name defaults to "modelValue". You can pass an additional object containing the prop's options and the model ref's value transform options.

defineModel examples and v-model consumption

Example: const model = defineModel() declares "modelValue" prop consumed by parent via v-model. Setting model.value = 'hello' emits "update:modelValue". const count = defineModel('count') declares "count" prop consumed by parent via v-model:count, and count.value++ emits "update:count". const model = defineModel({ type: String }) declares "modelValue" prop with type options.

defineModel de-synchronization warning with default values

If you have a `default` value for `defineModel` prop and don't provide any value for this prop from the parent component, it can cause de-synchronization between parent and child components. For example, the parent's ref could be undefined while the child's model has the default value of 1.

defineModel modifiers and transformers

To access modifiers used with the `v-model` directive, destructure the return value of `defineModel()`: const [modelValue, modelModifiers] = defineModel(). Use the `get` and `set` transformer options to transform the value when reading or syncing it back to the parent.

defineModel transformer example with trim modifier

Example: const [modelValue, modelModifiers] = defineModel({set(value) {if (modelModifiers.trim) {return value.trim()} return value}}). This transforms and returns the trimmed value when the .trim modifier is used with v-model, otherwise returns the value as-is.

defineModel TypeScript type parameters

Like `defineProps` and `defineEmits`, `defineModel` can receive type arguments to specify the types of the model value and modifiers: const modelValue = defineModel<string>() returns Ref<string | undefined>. Using required: true removes the undefined: const modelValue = defineModel<string>({ required: true }) returns Ref<string>. Modifiers are specified as the second type parameter: const [modelValue, modifiers] = defineModel<string, 'trim' | 'uppercase'>()

v-model directive definition and purpose

The v-model directive is used on a component to implement two-way binding. This means that when a parent component binds a value with v-model to a child component, the child can both read the value and emit updates that sync back to the parent.

defineModel() macro in Composition API

The recommended approach in Vue 3.4+ is to use the defineModel() macro in <script setup> to handle v-model. It returns a ref whose .value is synced with the parent's v-model binding. The macro automatically declares a prop named 'modelValue' and emits an 'update:modelValue' event under the hood.

defineModel() syntax and usage example

In the child component, use: const model = defineModel(). In the template, bind it to an input with v-model="model". The parent binds with <Child v-model="countModel" />. Example: <script setup> const model = defineModel() function update() { model.value++ } </script> <template> <div>Parent bound v-model is: {{ model }}</div> <button @click="update">Increment</button> </template>

v-model syntactic sugar desugaring

v-model="foo" on a component is compiled to :modelValue="foo" @update:modelValue="$event => (foo = $event)". This shows that v-model is syntactic sugar for binding a prop named 'modelValue' and listening to an 'update:modelValue' event.

defineModel() with prop options

You can pass options to defineModel() to configure the underlying prop. Syntax: const model = defineModel({ required: true }) or const model = defineModel({ default: 0 }). Options are passed as an object after the model name if using named v-models.

v-model default value desynchronization pitfall

If you provide a default value in defineModel() but the parent does not provide a value for the prop, the parent and child will be desynchronized. The parent's ref will be undefined while the child's model will have the default value. This is a warning scenario to avoid.

v-model with named arguments syntax

v-model can accept an argument to sync to a different prop. Syntax: <MyComponent v-model:title="bookTitle" />. In the child component with defineModel(), pass the prop name as the first argument: const title = defineModel('title'). This replaces the default 'modelValue' prop with a custom named prop.

defineModel() with named argument example

Child component example for v-model:title: <script setup> const title = defineModel('title') </script> <template> <input type="text" v-model="title" /> </template> Parent usage: <MyComponent v-model:title="bookTitle" />

Multiple v-model bindings on single component

A single component can have multiple v-model bindings with different arguments. Each v-model syncs to a different prop without extra configuration. Example parent: <UserName v-model:first-name="first" v-model:last-name="last" />. In child, define each with separate defineModel() calls.

Multiple v-model bindings example

Child component with multiple v-models: <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>

v-model modifiers access in defineModel()

Modifiers passed to v-model can be accessed by destructuring the defineModel() return value. Syntax: const [model, modifiers] = defineModel(). The modifiers object contains boolean flags for each modifier applied to the v-model binding.

v-model modifier example with capitalize

Example of using v-model.capitalize="myText" in parent. Child component receives and processes the modifier: <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>

defineModel() get and set options for modifiers

defineModel() accepts get and set options to transform values based on modifiers. The set option receives the value being set and should return a transformed value. This allows conditional modification based on which modifiers are applied to the v-model binding.

v-model with arguments and modifiers syntax

v-model can have both an argument and modifiers together. Syntax: <MyComponent v-model:title.capitalize="myText" />. In child with defineModel(), destructure both the model ref and modifiers when using named v-models: const [title, titleModifiers] = defineModel('title').

Options API v-model implementation

In Options API, v-model on a component requires: 1) A prop named 'modelValue' that receives the parent's value, 2) An emitted event 'update:modelValue' that sends the new value back. Example child component: export default { props: ['modelValue'], emits: ['update:modelValue'] } <template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /> </template>

Options API v-model with computed property

Alternative Options API v-model implementation using a writable computed property: export default { props: ['modelValue'], emits: ['update:modelValue'], computed: { value: { get() { return this.modelValue }, set(value) { this.$emit('update:modelValue', value) } } } } <template> <input v-model="value" /> </template>

Options API v-model with named argument

For Options API with v-model:title, the child component must declare a prop named 'title' (not 'modelValue') and emit 'update:title' (not 'update:modelValue'). Example: export default { props: ['title'], emits: ['update:title'] } <template> <input type="text" :value="title" @input="$emit('update:title', $event.target.value)" /> </template>

Options API v-model modifiers

In Options API, modifiers are provided via a prop named 'modelModifiers' that defaults to an empty object. To access modifiers, declare the prop: props: { modelValue: String, modelModifiers: { default: () => ({}) } } The modelModifiers object contains boolean flags for each modifier applied to the v-model binding.

Options API v-model modifier example

Options API example handling the capitalize modifier: 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) } } } <template> <input type="text" :value="modelValue" @input="emitValue" /> </template>

Options API v-model with argument and modifiers prop name

For v-model with both argument and modifiers in Options API, the modifier prop name is: argument + 'Modifiers'. Example: v-model:title.capitalize="myText" generates a prop 'titleModifiers' that contains { capitalize: true }. Declare it in props: props: ['title', 'titleModifiers']

Options API multiple v-model with modifiers example

Options API example with multiple v-models and modifiers: 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 } } } Usage: <UserName v-model:first-name.capitalize="first" v-model:last-name.uppercase="last" />

Composition API multiple v-model with modifiers example

Composition API example with multiple v-models and modifiers: <script setup> const [firstName, firstNameModifiers] = defineModel('firstName') const [lastName, lastNameModifiers] = defineModel('lastName') console.log(firstNameModifiers) // { capitalize: true } console.log(lastNameModifiers) // { uppercase: true } </script> Usage: <UserName v-model:first-name.capitalize="first" v-model:last-name.uppercase="last" />

v-model directive two-way binding

v-model creates a two-way binding on a form input element or a component. It is limited to <input>, <select>, <textarea>, and components. The expected value type varies based on the form input element or output of components. v-model supports three modifiers: .lazy listens to change events instead of input; .number casts valid input string to numbers; .trim trims input.

Give your agent this brain