Componente Textarea
Llegamos al último de nuestros componentes de formulario para este curso.
Con todo lo que hemos aprendido en este tutorial veremos lo fácil que es construir el AppTextarea
ya que prácticamente es muy parecido al componente AppInput
.
¡Vamos a sumergirnos!
Crear el Archivo AppTextarea.vue
Como hemos venido haciendo, vamos a crear un nuevo archivo de componente llamado AppTextarea.vue
y copiaremos el elemento textarea
, junto con su respectivo label
, en el nuevo archivo dentro de una etiqueta template
.
📃AppTextarea.vue
<template>
<label>Description</label>
<textarea
v-model="form.description"
placeholder="Description"
class="field"
></textarea>
</template>
Como hemos venido haciendo permitiremos que nuestro componente reciba una propiedad label
del padre. Para hacer esto, vamos a crear una propiedad label
. Esta propiedad se usará no solo para nuestro elemento <label>
, sino también como placeholder
, por lo que es muy conveniente que solo tengamos que definirlo una vez en el padre.
📃AppTextarea.vue
<script setup lang="ts">
withDefaults(defineProps<{
label?: string
}>(), {
label: ''
})
</script>
Como hemos venido haciendo, la propiedad label
es de tipo string
. Su valor por defecto será una cadena vacia en caso de no ser suministrada.
Ahora podemos usar nuestra nueva propiedad label
a través de la interpolación dentro del elemento <label>
de nuestro template
. Vinculemos también el atributo placeholder
a nuestra propiedad label
.
Esto asegurará que tanto el texto de placeholder
, dentro del elemento <textarea>
, como el label
estén coordinados y sean reactivos.
📃AppTextarea.vue
<script setup lang="ts">
withDefaults(defineProps<{
label?: string
}>(), {
label: ''
})
</script>
<template>
<label v-if="label">{{ label }}</label>
<textarea
v-model="form.description"
:placeholder="label"
class="field"
></textarea>
</template>
v-model
: Vinculando valor
Ahora que nuestro componente tiene su estructura básica, podemos pasar a agregar la capacidad para que nuestro componente esté listo para el v-model
.
Avancemos y agreguemos esta nueva propiedad, y luego vincúlela al atributo value
de nuestro elemento <textarea>
.
Lo usaremos por defecto como una cadena vacía, pero especificaremos string
y number
como los tipos permitidos.
📃AppTextarea.vue
<script setup lang="ts">
withDefaults(defineProps<{
label?: string
modelValue?: string | number
}>(), {
label: '',
modelValue: ''
})
</script>
<template>
<label v-if="label">{{ label }}</label>
<textarea
:value="modelValue"
:placeholder="label"
class="field"
></textarea>
</template>
Ahora hagamos la segunda parte del enlace bidireccional del v-model
: emitir el evento.
v-model
: Emitir el update:modelValue
Al igual que hicimos con el componente AppInput
, avancemos y agreguemos un detector de eventos @input
a nuestro elemento <textarea>
y emitamos un evento update:modelValue
cada vez que ocurra un evento de entrada.
📃AppTextarea.vue
<template>
<label v-if="label">{{ label }}</label>
<textarea
:value="modelValue"
:placeholder="label"
@input="$emit('update:modelValue', ($event.target as HTMLInputElement).value)"
class="field"
></textarea>
</template>
Agregar un detector @input
a nuestro elemento textarea
nos permite activar el evento requerido cada vez que el usuario escribe algo en el campo textarea
.
Tenga en cuenta que estamos pasando el $event.target.value
como la carga útil del evento. Este es el valor que el v-modelo
recibirá en el padre.
Asignando los $attrs
al textarea
En el caso de nuestro componente AppTextArea.vue
, también queremos poder inyectar atributos directamente en el textarea
, por lo que debemos vincular manualmente el objeto $attrs
.
Avancemos y hagámoslo agregando v-bind="$attrs"
a nuestro elemento <textarea>
.
📃AppTextarea.vue
<template>
<label v-if="label">{{ label }}</label>
<textarea
v-bind="$attrs"
:value="modelValue"
:placeholder="label"
@input="$emit('update:modelValue', ($event.target as HTMLInputElement).value)"
class="field"
></textarea>
</template>
Con este pequeño cambio, los elementos <textarea>
ahora recibirán correctamente los vínculos cols
y rows
del padre y se aplicarán nuestras clases CSS.
Componente padre TaskForm.vue
Regresemos a nuestro formulario y usemos nuestro nuevo componente AppTextarea.vue
en lugar de nuestro elemento nativo para probar nuestro código.
Reemplacemos el textarea
entrada de Description
en nuestro formulario con nuestro nuevo componente.
<AppTextarea
v-model="form.description"
label="Description"
/>
Solo nos falta declarar AppTextarea.vue
como complemento global para que esto funcione.
Terminando
Con la finalización de nuestro componente AppTextarea
, culminamos la creación de nuestros componentes de formulario. ¡Buen trabajo en lograrlo hasta el final!
En la siguiente lección, daremos un pequeño giro y veremos cómo podemos manejar el envío de formularios correctamente en Vue aprovechando el poder de una biblioteca ampliamente utilizada para realizar solicitudes HTTP: Axios.