Reputation: 2307
I am using a Laravel 9 application with Vue 3. I have created a fresh install. I want to create some components that I want to use in a parent component. The first component that I want to create is which will be passed a value (postal code) and the component will format and validate the passed value. The parent component should have access to the updated formatted value.
As a first step, I have created the postal-code-component using the documentation from vuejs.org.
<!-- postalcode.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>
Next, I made a copy of the example-component, that comes with the Laravel Vue installation to create a data element "postalcode" and use as a v-model for ,
<div class="card-body">
<postal-code-input v-model="postalcode" /> {{ postalcode }}
</div>
</template>
<script>
export default {
data(){
return {
postalcode:'l3r3g',
}
},
}
When I run my app, it displays the initial value (l3r3g) in the input box and also the same value at {{postalcode}}. However, when I update the value in the input box, it does not update {{postalcode}} in the parent component. When I inspect the component in vue dev tools, I see that modelValue and computed 'value' are undefined, as shown
I just don't know what is going on. I shall appreciate any help to fix this issue.
Upvotes: 1
Views: 989
Reputation: 940
I've tried by using watcher
instead of computed
property because the computed properties made cache and sometime it's set()
method created complications in debugging reactivity
.
Following snippet works for me:
// PostalCode.vue
<template>
<div class="input-group input-group-merge mb-3">
<input
v-model="postalCode"
type="text" class="form-control"
id="postal_code" name="postal_code"
/>
</div>
</template>
<script>
export default {
name: "PostalCode",
props: {
modelValue: String,
},
data() {
return {
postalCode: null
}
},
watch: {
// watching prop
modelValue: {
handler: function (newValue) {
if (newValue) {
this.postalCode = newValue;
}
},
immediate: true,
},
// watching data() property
postalCode: {
handler: function (newValue, old) {
this.$emit('update:modelValue', newValue)
},
immediate: true
}
}
}
</script>
<postal-code v-model="user.postal_code"/>
Your can also place your formatting logic within any watcher also.
depending on requirement, if you want to do formatting on props change by parent (for old and new both) then place formatting logic in modelValue
watcher.
Following snippet works perfectly on Vue3
Upvotes: 2
Reputation: 1277
If you’re using v-model to bind a prop like this
<postal-code-input v-model="postalcode" />
The postal-code component should emit ‘input’ and have a value prop. You can use a different prop and event but then you should avoid the v-model binding and just do something like this
<postal-code-input :modelValue="postalcode" @modelValueUpdate=“handleUpdate” />
Upvotes: 0