'How to correctly pass a v-model down to a Quasar q-input base component?
I am using Quasar to build my Vue app and I want to create a base component (a.k.a. presentational, dumb, or pure component) using q-input
.
I have a created a SFC named VInput.vue
as my base component, it looks like this:
<template>
<q-input
outlined
class="q-mb-md"
hide-bottom-space
/>
</template>
Then I created a SFC named TestForm.vue
that looks like this:
<template>
<q-form>
<v-input label="Email" v-model="email" />
</q-form>
</template>
<script setup lang="ts">
import VInput from './VInput.vue';
import { ref } from 'vue';
const email = ref('[email protected]');
</script>
The label="Email" v-model="email"
parts are passed down to my VInput.vue
base component and correctly rendered on the page.
But there is a typescript error on q-input
of the VInput.vue
base component because q-input
requires a v-model:
`Type '{ outlined: true; class: string; hideBottomSpace: true; "hide-bottom-space": boolean; }' is not assignable to type 'IntrinsicAttributes & VNodeProps & AllowedComponentProps & ComponentCustomProps & QInputProps'.`
`Property 'modelValue' is missing in type '{ outlined: true; class: string; hideBottomSpace: true; "hide-bottom-space": boolean; }' but required in type 'QInputProps'.ts(2322)`.
So how do I code the VInput.vue
base component without knowing the v-model value head of time?
I have come up with the below solution, which seems to work because I think the v-model passed down is overiding the base component v-model.
But I wanted to ask to make sure I wasn't screwing something up.
Is this the correct way of doing things? It seems hacky.
<template>
<q-input v-model="inputText" outlined class="q-mb-md" hide-bottom-space />
</template>
<script setup lang="ts">
const inputText = '';
</script>
Solution 1:[1]
I found a couple of solutions:
Solution 1
It involves splitting the v-model
into it seperate parts (:model-value
and @update:model-value
, and then passing in the text value as a prop.
Base component VInput.vue
:
<template>
<q-input
outlined
class="q-mb-md"
hide-bottom-space
:model-value="text"
@update:model-value="(value) => emit('update:text', value)"
/>
</template>
<script setup lang="ts">
defineProps({
text: {
required: false,
type: String,
},
});
const emit = defineEmits(['update:text']);
</script>
Solution 2
Extracting the prop and using toRef
on it.
<template>
<q-input outlined class="q-mb-md" hide-bottom-space v-model="textProp" />
</template>
<script setup lang="ts">
import { toRef } from 'vue';
const props = defineProps({
text: {
required: false,
type: String,
default: '',
},
});
const textProp = toRef(props, 'text');
</script>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | David Wolf |