I am trying to create a reusable Textarea component, using vee-validate 4.13.1 and
vue 3.4.21 and storybook Below the code of Textarea.vue
<template>
<FormControl :valid="isValid">
<label v-if="label" class="lib__form__label">{{ label }}</label>
<span v-if="description" class="lib__form__desc">{{ description }}</span>
<textarea
v-model="value"
:disabled
:name
:placeholder
:readonly="readOnly"
:required
class="lib__form__textarea"
rows="5"
>
</textarea>
<ErrorMessage v-if="!isValid" :id="errorMessagesId" :errors="errors" />
</FormControl>
</template>
<script lang="ts" setup>
import ErrorMessage from '@/components/display/ErrorMessage.vue'
import FormControl from '@/components/layout/FormControl.vue'
import { initTextarea } from '@assets/framework/js/textarea'
import { computed, onMounted } from 'vue'
import { useField } from 'vee-validate'
interface Props {
/** Permet d'indiquer si la textarea est requise ou non. */
required?: boolean
/** Permet d'indiquer si la textarea est désactivée (disabled) ou non. */
disabled?: boolean
/** Permet d'indiquer si la textaera est en mode lecture seule (readOnly) ou non. */
readOnly?: boolean
/** Propriété qui définit le label associé à la Textarea. */
label?: string | null
/** Propriété de type String qui permet d'ajouter une description sous le label. */
description?: string
/** Propriété qui définit la longueur maximale du texte que l'utilisateur peut saisir. */
placeholder?: string
/** Propriété qui définit le nom de la textarea. */
name: string
}
const props = withDefaults(defineProps<Props>(), {
label: null,
placeholder: '',
disabled: false,
required: false,
readOnly: false,
})
defineModel<string | null>({ required: true })
const { errors, value, meta } = useField<string | null>(props.name)
//Vérifier la validité de l'input après la saisie (renvoyer undefined au chargement du composant: utile pour le syle CSS)
const isValid = computed<boolean | undefined>(() =>
meta.dirty === false ? undefined : errors.value.length === 0
)
//IDs des messages d'erreurs relatives à l'input
const errorMessagesId = computed<string>(() => `error-messages-${props.name}`)
//Appel au script JS initTextArea
onMounted(() => initTextarea())
</script>
and here is the Story from Teaxtarea.stories.ts
export const DisabledReadOnly: Story = {
name: 'Disabled / ReadOnly',
render: () => ({
components: { Textarea },
setup() {
const disabledModelValue = ref('Cette zone de texte est désactivée')
const readonlyModelValue = ref('Cette zone de texte est en lecture seule')
console.log('Disabled Model Value:', disabledModelValue.value)
console.log('ReadOnly Model Value:', readonlyModelValue.value)
return { disabledModelValue, readonlyModelValue }
},
template: `
<div>
<!-- Disabled Textarea -->
<Textarea
v-model="disabledModelValue"
label="Disabled Textarea"
name="textareaDisabled"
:disabled="true"
/>
<!-- ReadOnly Textarea -->
<Textarea
v-model="readonlyModelValue"
label="ReadOnly Textarea"
name="textareaReadonly"
:readOnly="true"
/>
</div>
`
})
}
the disabledModelValue and readonlyModelValue are logged correctly but not displayed in the two textarea, I think i am using defineModel() in a wrong way. Or i should synchronize value and defineModel()
defineModel<string | null>({ required: true })
const { errors, value, meta } = useField<string | null>(props.name)
How can I correct my component?
3