Componente Checkbox
Anteriormente, en este tutorial, creamos componentes reutilizables para dos entradas HTML importantes: AppInput
y AppSelect
para los elementos input
y select
, respectivamente. En esta lección, asumimos el nuevo desafío de crear un componente reutilizable para nuestras entradas de checkbox
.
El objetivo sigue siendo el mismo, el componente debe ser altamente reutilizable y capaz de aceptar vinculaciones de
v-model
.
¡Vamos a sumergirnos!
AppCheckbox.vue
Primero, crearemos un nuevo archivo, AppCheckbox.vue
dentro de la carpeta components
.
Vamos a agregar un bloque template
y copiar el input
con type="checkbox"
de nuestro archivo TasksForm.vue
que contiene el control para el "Reviewed"
.
📃AppCheckbox.vue
<template>
<input
type="checkbox"
v-model="form.supervision.reviewed"
class="field"
/>
<label>Reviewed</label>
</template>
Como hemos hecho en nuestros otros componentes, vamos a abordar primero el label
.
Primero el label
Necesitamos asegurarnos de que tenemos una forma de inyectar un label
en este componente, por lo que vamos a agregar una propiedad label
para que el padre pueda pasarla a nuestro componente.
Avancemos y agreguemos esa propiedad y vinculémosla al label
.
📃AppCheckbox.vue
<script setup lang="ts">
withDefaults(defineProps<{
label?: string
}>(), {
label: ''
})
</script>
<template>
<input
type="checkbox"
v-model="form.supervision.reviewed"
class="field"
/>
<label v-if="label">{{ label }}</label>
</template>
Tenga en cuenta que hemos agregado una condición v-if
para verificar que la propiedad label
esté establecida antes de representar el elemento <label>
. No hay una razón real para representar un elemento <label>
vacío y, lo que es peor, ¡no queremos etiquetarlo como una cadena vacía!
Hay varias consideraciones de accesibilidad cuando se habla de etiquetas y entradas, y lo que hemos estado haciendo hasta ahora en su mayoría no será accesible. Sin embargo, en una lección posterior revisaremos estos componentes cuando echemos un vistazo a los conceptos básicos de accesibilidad en los formularios.
Haciéndolo compatible con v-model
Ahora que nuestro label
ha sido configurado, pasemos a hacerlo para que el componente pueda aceptar vínculos de v-model
.
Las casillas de verificación tienen algunas peculiaridades que debemos tener en cuenta antes de comenzar a configurar nuestros vínculos.
- La primera es que las entradas de casillas de verificación vinculan su estado a una propiedad
checked
, y no directamente alvalue
.
La propiedad
value
de casillas de verificación generalmente no se usa en el frontend, ya que su objetivo principal es proporcionar unvalue
cuando se envía al backend a través de un botónsubmit
. Si se omite, este valor está activado de manera predeterminada, lo que está bien para la mayoría de las aplicaciones, ya que la mayoría de los formularios se manejarán a través de un post asíncrono y las variables pasadas al backend están controladas por el código del frontend.
- La segunda cosa que debemos tener en cuenta es que las entradas tipo
checkbox
no activan eventosinput
, sino eventoschange
cada vez que se seleccionan y deseleccionan.
Ahora que estamos armados con este conocimiento, agreguemos nuestra propiedad modelValue
, que contendrá la primera parte de nuestro vínculo bidireccional: permitir que el padre inyecte un estado para el checkbox
.
📃AppCheckbox.vue
withDefaults(defineProps<{
label?: string
modelValue?: boolean
}>(), {
label: '',
modelValue: false
})
A continuación, vayamos al template
y reemplacemos el vínculo del v-model
que se copió y pegó desde el formulario de demostración anterior con nuestro nuevo vínculo :checked
en nuestra propiedad modelValue
.
<template>
<input
type="checkbox"
:checked="modelValue"
class="field"
/>
<label v-if="label">{{ label }}</label>
</template>
Finalmente, debemos emitir update:modelValue
cada vez que queramos alertar al padre que la casilla de verificación se ha activado. Escucharemos el evento @change
en el elemento input
y emitiremos el nuevo estado comprobado de nuestro elemento cada vez que se active.
Tenga en cuenta que para las casillas de verificación no estamos emitiendo el value
de target
a través de $event.target.value
, sino el estado de checked
a través de $event.target.checked
.
📃AppCheckbox.vue
<input
v-bind="$attrs"
type="checkbox"
:checked="modelValue"
@change="$emit('update:modelValue', ($event.target as HTMLInputElement).checked)"
class="field"
/>
A su vez avanzamos y agregamos v-bind="$attrs"
a nuestro elemento para poder permitir la inyección de atributos en el elemento correcto. Ahora recibirán correctamente el vínculo del padre.
Usando nuestro nuevo componente
Ahora que nuestro componente está listo, podemos volver a TasksForm.vue
y reemplazar las casillas de verificación Reviewed
y Approved
con nuestro nuevo componente AppCheckbox
.
📃TasksForm.vue
<h3>Supervision</h3>
<div>
<AppCheckbox
v-model="form.supervision.reviewed"
label="Reviewed"
/>
</div>
<div>
<AppCheckbox
v-model="form.supervision.approved"
label="Approved"
/>
</div>
Solo falta importarlo como complemento.
Complemento Global
Vamos a importarlo globalmente, igual como se dijo en la lección anterior.
📃main.ts
import { createApp } from 'vue'
import App from './App.vue'
import AppInput from '@/components/AppInput.vue'
import AppSelect from '@/components/AppSelect.vue'
import AppCheckbox from '@/components/AppCheckbox.vue'
import './index.css'
createApp(App)
.component('AppInput', AppInput)
.component('AppSelect', AppSelect)
.component('AppCheckbox', AppCheckbox)
.mount('#app')
Vayamos a nuestro navegador y activemos y desactivemos las casillas de verificación para asegurarnos de que los vínculos funcionen.
Terminando
Las casillas de verificación tienen algunas peculiaridades que tuvimos que aprender para crear nuestro componente AppCheckbox
.
En nuestra próxima lección, abordaremos nuestro componente, AppRadio
para botones de radio
, y veremos qué los hace especiales y, a veces, difíciles de manejar.