
Cómo construir un Multiselect Dropdown en 4 Frameworks modernos
Vamos a construir un componente multiselect desde cero usando React y Tailwind CSS, que nos permitirá seleccionar múltiples opciones desde un dropdown y mostrar en consola las opciones seleccionadas. Empezaremos con React ya que es lo que más hemos visto hasta ahora.
Paso 1: Crear la estructura base del componente
Primero vamos a crear el layout base del componente usando sólo HTML y clases de Tailwind. Esto nos permite enfocarnos primero en el diseño sin preocuparnos por la lógica todavía.
Creamos un archivo: MultiSelectDropdown.tsx
Y pegamos esta estructura:
export default function MultiSelectDropdown() {
return (
<div className="w-60 m-auto">
<button
type="button"
className="text-white justify-between w-full bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Dropdown button
<svg
className="w-2.5 h-2.5 ml-3"
viewBox="0 0 10 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 1L5 5L9 1"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>
{/* Dropdown visible por ahora */}
<div className="z-10 w-full mt-2 block bg-white divide-y divide-gray-100 rounded-lg shadow-sm dark:bg-gray-700">
<ul className="p-3 space-y-3 text-sm text-gray-700 dark:text-gray-200">
<li>
<label className="flex items-center gap-2">
<input type="checkbox" />
React
</label>
</li>
<li>
<label className="flex items-center gap-2">
<input type="checkbox" />
Vue
</label>
</li>
</ul>
</div>
</div>
);
}
¿Qué hicimos aquí?
-
Creamos un contenedor de ancho fijo centrado.
-
Agregamos un botón con estilos de Tailwind (
bg-blue-700
,rounded-lg
, etc.). -
Insertamos una lista de opciones de ejemplo.
-
Todo el diseño es estático todavía, sin funcionalidad.
Paso 2: Manejar la apertura y cierre del dropdown
Ahora vamos a hacer que el dropdown se oculte o muestre cuando hacemos clic en el botón.
import { useState } from "react";
export default function MultiSelectDropdown() {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="w-60 m-auto">
<button
type="button"
onClick={() => setIsOpen((prev) => !prev)}
className="text-white justify-between w-full bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Dropdown button
<svg
className="w-2.5 h-2.5 ml-3"
viewBox="0 0 10 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 1L5 5L9 1"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>
{isOpen && (
<div className="z-10 w-full mt-2 block bg-white divide-y divide-gray-100 rounded-lg shadow-sm dark:bg-gray-700">
<ul className="p-3 space-y-3 text-sm text-gray-700 dark:text-gray-200">
<li>
<label className="flex items-center gap-2">
<input type="checkbox" />
React
</label>
</li>
<li>
<label className="flex items-center gap-2">
<input type="checkbox" />
Vue
</label>
</li>
</ul>
</div>
)}
</div>
);
}
¿Qué aprendemos aquí?
-
React usa
useState
para manejar el estado de apertura del menú. -
Con
{isOpen && (...)}
mostramos u ocultamos el dropdown de forma condicional. -
Esto ya nos permite ver el menú al hacer clic, y ocultarlo al hacer clic de nuevo.
Paso 3: Crear opciones dinámicas
Ahora definimos una lista de opciones para renderizarlas dinámicamente. Así podemos cambiar fácilmente las opciones más adelante sin repetir código (Por el momento dentro del componente pero se puede fácilmente pasar como prop).
const options = [
{ label: "React", value: "react" },
{ label: "Vue", value: "vue" },
{ label: "Svelte", value: "svelte" },
{ label: "Solid", value: "solid" },
{ label: "Angular", value: "angular" },
];
Y en lugar de escribir <li>
manualmente, iteramos con .map()
:
<ul className="p-3 space-y-3 text-sm text-gray-700 dark:text-gray-200">
{options.map((option) => (
<li key={option.value}>
<label className="flex items-center gap-2">
<input type="checkbox" />
{option.label}
</label>
</li>
))}
</ul>
Paso 4: Guardar y manejar las opciones seleccionadas
Ahora implementamos la lógica para guardar las selecciones. Creamos una nueva variable de estado llamada selected
que guardará un array con los valores seleccionados.
Además, queremos que cada vez que se seleccione o deseleccione algo, se haga un console.log()
del array actualizado. Para evitar logs duplicados, lo haremos con useEffect
.
import { useState, useEffect } from "react";
export default function MultiSelectDropdown() {
const [isOpen, setIsOpen] = useState(false);
const [selected, setSelected] = useState<string[]>([]);
// Este efecto imprime en consola cada vez que cambia la selección
useEffect(() => {
console.log("Seleccionadas:", selected);
}, [selected]);
const handleChange = (value: string) => {
setSelected((prev) =>
prev.includes(value)
? prev.filter((v) => v !== value)
: [...prev, value]
);
};
const options = [
{ label: "React", value: "react" },
{ label: "Vue", value: "vue" },
{ label: "Svelte", value: "svelte" },
{ label: "Solid", value: "solid" },
{ label: "Angular", value: "angular" },
];
return (
<div className="w-60 m-auto">
<button
onClick={() => setIsOpen((prev) => !prev)}
type="button"
className="text-white justify-between w-full bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 inline-flex items-center"
>
Dropdown button
<svg className="w-2.5 h-2.5 ml-3" /* ... */ />
</button>
{isOpen && (
<div className="z-10 w-full mt-2 block bg-white rounded-lg shadow-sm">
<ul className="p-3 space-y-3 text-sm text-gray-700">
{options.map((option) => (
<li key={option.value}>
<label className="flex items-center gap-2">
<input
type="checkbox"
checked={selected.includes(option.value)}
onChange={() => handleChange(option.value)}
/>
{option.label}
</label>
</li>
))}
</ul>
</div>
)}
</div>
);
}
Resultado
Ya tenemos un componente 100% funcional en React:
-
Visualmente estilizado con Tailwind.
-
Dropdown desplegable al clic.
-
Permite seleccionar y deseleccionar múltiples opciones.
-
Imprime en consola las opciones seleccionadas sin duplicados.
Multiselect Dropdown en Vue 3 + Tailwind + TypeScript
Aquí replicamos el mismo componente de React, pero usando Vue 3, Composition API, TypeScript y Tailwind. Lo haremos desde cero, en pasos simples y comentados.
-
Mostrará un botón para desplegar un menú con opciones.
-
Permitirá seleccionar múltiples opciones (checkboxes).
-
Al seleccionar/deseleccionar, actualizará un array reactivo.
-
Imprimirá en consola las opciones seleccionadas (sin duplicados).
-
Usará Tailwind CSS para estilos.
Paso 1: Crear la estructura del componente
Creamos el archivo:
src/components/MultiSelectDropdown.vue
Y comenzamos con la estructura mínima:
<template>
<div class="w-60 m-auto">
<button
type="button"
class="text-white justify-between w-full bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 inline-flex items-center"
>
Dropdown button
<svg
class="w-2.5 h-2.5 ml-3"
viewBox="0 0 10 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 1L5 5L9 1"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
<div class="z-10 w-full mt-2 block bg-white divide-y divide-gray-100 rounded-lg shadow-sm">
<ul class="p-3 space-y-3 text-sm text-gray-700">
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
React
</label>
</li>
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
Vue
</label>
</li>
</ul>
</div>
</div>
</template>
<script setup lang="ts">
// Lógica vendrá después
</script>
¿Qué hicimos aquí?
-
Creamos la estructura visual: un botón y un dropdown con dos opciones fijas.
-
Usamos Tailwind para el diseño (botón azul, checkbox alineado).
-
No hay interactividad aún: ni apertura/cierre, ni selección.
Este paso sirve para tener el esqueleto visual listo antes de agregar la lógica.
Paso 2: Mostrar/Ocultar el dropdown con ref()
Queremos que el dropdown solo se muestre cuando hagamos clic en el botón. Para eso:
-
Creamos una variable reactiva llamada
isOpen
-
Usamos
v-if="isOpen"
para mostrar el menú -
Alternamos el valor con un método
toggleDropdown()
Actualizamos el componente así:
<template>
<div class="w-60 m-auto">
<!-- Botón que abre/cierra el dropdown -->
<button
type="button"
@click="toggleDropdown"
class="text-white justify-between w-full bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 inline-flex items-center"
>
Dropdown button
<svg
class="w-2.5 h-2.5 ml-3"
viewBox="0 0 10 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 1L5 5L9 1"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
<!-- Mostramos el dropdown solo si isOpen es true -->
<div
v-if="isOpen"
class="z-10 w-full mt-2 block bg-white divide-y divide-gray-100 rounded-lg shadow-sm"
>
<ul class="p-3 space-y-3 text-sm text-gray-700">
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
React
</label>
</li>
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
Vue
</label>
</li>
</ul>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const isOpen = ref(false)
const toggleDropdown = () => {
isOpen.value = !isOpen.value
}
</script>
¿Qué aprendimos aquí?
-
ref(false)
crea una variable reactiva en Vue. -
Usamos
v-if="isOpen"
para mostrar el menú condicionalmente. -
Al hacer clic en el botón,
toggleDropdown()
invierte su valor (true
/false
).
Ya tenemos la interacción básica lista. ¡Se ve como un dropdown real!
Paso 3: Mostrar opciones desde un array con v-for
Hasta ahora, las opciones están “quemadas” en el HTML. Vamos a moverlas a un array para que el componente sea dinámico y reusable.
1. Creamos un array de opciones en el <script setup>
Usamos TypeScript para tipar las opciones:
interface Option {
label: string
value: string
}
const options: Option[] = [
{ label: 'React', value: 'react' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte' },
{ label: 'Solid', value: 'solid' },
{ label: 'Angular', value: 'angular' }
]
2. Reemplazamos los <li>
fijos por un v-for
Actualizamos el template
:
<ul class="p-3 space-y-3 text-sm text-gray-700">
<li v-for="option in options" :key="option.value">
<label class="flex items-center gap-2">
<input type="checkbox" />
{{ option.label }}
</label>
</li>
</ul>
¿Qué logramos aquí?
-
El componente ahora usa un array tipado con
Option[]
, lo que facilita reusarlo. -
Con
v-for
, renderizamos tantas opciones como queramos sin duplicar código. -
Vue se encarga de mantener la eficiencia del DOM con
:key="option.value"
.
Paso 4: Manejar selección múltiple (checkboxes)
Ahora queremos que:
-
Cada checkbox represente una opción seleccionable.
-
Las opciones seleccionadas se guarden en un array
selected
. -
Si ya está seleccionada, se deseleccione (toggle).
-
Se imprima en consola cada vez que el array cambie.
1. Creamos el estado selected
En el <script setup>
:
import { ref, watch } from 'vue'
const selected = ref<string[]>([])
2. Creamos una función para agregar o quitar selecciones
const toggleSelection = (value: string) => {
if (selected.value.includes(value)) {
selected.value = selected.value.filter(v => v !== value)
} else {
selected.value.push(value)
}
}
3. Escuchamos los cambios con watch
(como useEffect
en React)
Usamos :checked
y @change
para enlazar con el estado:
<input
type="checkbox"
:checked="selected.includes(option.value)"
@change="toggleSelection(option.value)"
/>
Resultado
Ahora el componente:
-
Permite seleccionar múltiples opciones.
-
Guarda las seleccionadas en un array.
-
Hace
console.log()
al cambiar la selección.
Multiselect Dropdown en Svelte + Tailwind + TypeScript
Paso 1: Estructura HTML + Tailwind base
Vamos a comenzar por construir solo la estructura visual estática del componente, sin lógica aún. El objetivo es ver cómo se verá el dropdown, el botón y las opciones con checkboxes, usando únicamente HTML y Tailwind CSS.
Código inicial: MultiSelectDropdown.svelte
<script lang="ts">
// lógica vendrá después
</script>
<div class="w-60 m-auto">
<!-- Botón para abrir el dropdown -->
<button
type="button"
class="text-white justify-between w-full bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 inline-flex items-center"
>
Dropdown button
<svg
class="w-2.5 h-2.5 ml-3"
viewBox="0 0 10 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 1L5 5L9 1"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
<!-- Dropdown (visible todo el tiempo por ahora) -->
<div
class="z-10 w-full mt-2 block bg-white divide-y divide-gray-100 rounded-lg shadow-sm"
>
<ul class="p-3 space-y-3 text-sm text-gray-700">
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
React
</label>
</li>
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
Vue
</label>
</li>
</ul>
</div>
</div>
¿Qué tenemos hasta ahora?
-
Un botón con diseño responsivo (
w-full
,bg-blue-700
,hover
,rounded-lg
). -
Un ícono de flecha hacia abajo (
svg
). -
Un menú tipo dropdown con dos opciones de ejemplo (
React
,Vue
) como<li>
. -
Cada opción es un
<label>
que contiene un checkbox y un texto.
Paso 2: Mostrar/Ocultar el dropdown con una variable reactiva
Ahora vamos a hacer que el dropdown se abra y cierre al hacer clic en el botón, usando reactividad en Svelte con let
.
¿Cómo lo haremos?
-
Creamos una variable
isOpen
conlet
-
Alternamos su valor al hacer clic en el botón
-
Mostramos el dropdown solo si
isOpen === true
usando{#if}
Código actualizado
<script lang="ts">
let isOpen = false;
function toggleDropdown() {
isOpen = !isOpen;
}
</script>
<div class="w-60 m-auto">
<!-- Botón con evento on:click -->
<button
type="button"
on:click={toggleDropdown}
class="text-white justify-between w-full bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 inline-flex items-center"
>
Dropdown button
<svg
class="w-2.5 h-2.5 ml-3"
viewBox="0 0 10 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 1L5 5L9 1"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
<!-- Mostrar dropdown solo si isOpen es true -->
{#if isOpen}
<div
class="z-10 w-full mt-2 block bg-white divide-y divide-gray-100 rounded-lg shadow-sm"
>
<ul class="p-3 space-y-3 text-sm text-gray-700">
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
React
</label>
</li>
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
Vue
</label>
</li>
</ul>
</div>
{/if}
</div>
¿Qué aprendimos aquí?
-
En Svelte,
let
crea variables reactivas automáticamente. -
on:click={toggleDropdown}
es la forma de escuchar eventos. -
{#if ...}
es comov-if
en Vue o un render condicional en React ({isOpen && (...)}
).
Paso 3: Mostrar las opciones dinámicamente con {#each}
Hasta ahora, las opciones (React
, Vue
) están escritas directamente en el HTML. Ahora vamos a moverlas a un array tipado para que el componente sea dinámico y escalable.
1. Creamos el array de opciones en el <script>
interface Option {
label: string;
value: string;
}
const options: Option[] = [
{ label: 'React', value: 'react' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte' },
{ label: 'Solid', value: 'solid' },
{ label: 'Angular', value: 'angular' },
];
Option
es una interfaz que usamos para tipar las opciones. Esto es posible gracias a que activaste TypeScript
2. Reemplazamos los <li>
fijos por {#each}
<ul class="p-3 space-y-3 text-sm text-gray-700">
{#each options as option (option.value)}
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
{option.label}
</label>
</li>
{/each}
</ul>
¿Qué logramos?
-
Las opciones ya no están duplicadas manualmente.
-
Podemos fácilmente agregar, quitar o pasar las opciones como
props
después. -
Cada opción se representa con un checkbox y su
label
.
Paso 4: Manejar selección múltiple y mostrarla en consola
Queremos que el componente:
-
Permita seleccionar múltiples opciones (con checkboxes).
-
Guarde las opciones seleccionadas en un array.
-
Haga
console.log()
del array cada vez que cambie.
¿Cómo lo haremos?
-
Creamos un array reactivo
selected: string[]
. -
Usamos
bind:checked
para vincular cada checkbox con el estado. -
O mejor: manejamos el
on:change
manualmente, como hicimos en Vue y React (para control total). -
Imprimimos con
$: console.log(...)
que es comowatch
ouseEffect
.
1. Creamos selected
y toggleSelection()
let selected: string[] = [];
function toggleSelection(value: string) {
if (selected.includes(value)) {
selected = selected.filter((v) => v !== value);
} else {
selected = [...selected, value];
}
}
// log reactivo
$: console.log('Seleccionadas:', selected);
2. Actualizamos los checkboxes
En cada input, usamos:
<input
type="checkbox"
checked={selected.includes(option.value)}
on:change={() => toggleSelection(option.value)}
/>
¿Qué logramos?
-
El dropdown ya permite selección múltiple.
-
Los checkboxes reflejan el estado real.
-
Cada cambio en
selected
hace unconsole.log()
sin duplicados. -
Comportamiento igual al de React y Vue
Multiselect Dropdown en Angular + Tailwind + TypeScript
Paso 1: Estructura HTML + Tailwind base
Primero, creamos solo la estructura visual del componente, sin lógica aún. Esto nos permite ver el diseño del botón y el menú desplegable.
1. Crear el componente
Desde la terminal, en el proyecto Angular:
ng generate component components/multi-select-dropdown
Esto creará 4 archivos dentro de src/app/components/multi-select-dropdown
:
-
multi-select-dropdown.component.ts
-
multi-select-dropdown.component.html
-
multi-select-dropdown.component.css
-
multi-select-dropdown.component.spec.ts
2. Usar el componente en app.component.html
Edita el archivo src/app/app.component.html
y agrega:
<app-multi-select-dropdown></app-multi-select-dropdown>
3. Estructura HTML base en multi-select-dropdown.component.html
Pegamos la estructura visual básica con Tailwind:
<div class="w-60 m-auto">
<!-- Botón que abre el dropdown -->
<button
type="button"
class="text-white justify-between w-full bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 inline-flex items-center"
>
Dropdown button
<svg
class="w-2.5 h-2.5 ml-3"
viewBox="0 0 10 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 1L5 5L9 1"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
<!-- Dropdown visible por ahora (sin lógica) -->
<div
class="z-10 w-full mt-2 block bg-white divide-y divide-gray-100 rounded-lg shadow-sm"
>
<ul class="p-3 space-y-3 text-sm text-gray-700">
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
React
</label>
</li>
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
Vue
</label>
</li>
</ul>
</div>
</div>
Resultado esperado
Si recargas http://localhost:4200, deberías ver:
-
Un botón azul que dice “Dropdown button”
-
Un dropdown con dos opciones (React y Vue)
-
Estilo limpio con Tailwind
Paso 2: Mostrar/Ocultar el dropdown con una variable en el componente
Queremos que el dropdown:
-
Se muestre al hacer clic en el botón.
-
Se oculte al volver a hacer clic.
¿Cómo lo haremos?
-
Creamos una propiedad booleana
isOpen
en el.ts
. -
Hacemos toggle con un método
toggleDropdown()
. -
En el HTML, usamos
*ngIf="isOpen"
para mostrar/ocultar el menú.
1. Agregar lógica en el archivo .ts
Edita multi-select-dropdown.component.ts
:
import { Component } from '@angular/core';
@Component({
selector: 'app-multi-select-dropdown',
templateUrl: './multi-select-dropdown.component.html',
styleUrls: ['./multi-select-dropdown.component.css'],
})
export class MultiSelectDropdownComponent {
isOpen = false;
toggleDropdown(): void {
this.isOpen = !this.isOpen;
}
}
2. Conectar el botón al método
Edita multi-select-dropdown.component.html
:
<!-- Botón con (click) -->
<button
type="button"
(click)="toggleDropdown()"
class="text-white justify-between w-full bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 inline-flex items-center"
>
Dropdown button
<svg
class="w-2.5 h-2.5 ml-3"
viewBox="0 0 10 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 1L5 5L9 1"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
3. Mostrar el dropdown condicionalmente
Reemplaza el div
del dropdown así:
<div
*ngIf="isOpen"
class="z-10 w-full mt-2 block bg-white divide-y divide-gray-100 rounded-lg shadow-sm"
>
<ul class="p-3 space-y-3 text-sm text-gray-700">
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
React
</label>
</li>
<li>
<label class="flex items-center gap-2">
<input type="checkbox" />
Vue
</label>
</li>
</ul>
</div>
Resultado
Ahora al hacer clic en el botón:
-
El menú aparece y desaparece.
-
El estado lo maneja
isOpen
con un simple toggle.
Paso 3: Mostrar las opciones dinámicamente desde un array
Hasta ahora, las opciones (React, Vue) están escritas directamente en el HTML. Vamos a moverlas a un array tipado en TypeScript y usar *ngFor
para renderizarlas dinámicamente.
1. Declarar la interfaz y el array de opciones
Edita multi-select-dropdown.component.ts
:
interface Option {
label: string;
value: string;
}
export class MultiSelectDropdownComponent {
isOpen = false;
options: Option[] = [
{ label: 'React', value: 'react' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte' },
{ label: 'Solid', value: 'solid' },
{ label: 'Angular', value: 'angular' }
];
toggleDropdown(): void {
this.isOpen = !this.isOpen;
}
}
2. Usar *ngFor
para renderizar el listado en el HTML
En multi-select-dropdown.component.html
, reemplaza los <li>
fijos por:
<ul class="p-3 space-y-3 text-sm text-gray-700">
<li *ngFor="let option of options">
<label class="flex items-center gap-2">
<input type="checkbox" />
{{ option.label }}
</label>
</li>
</ul>
¿Qué logramos?
-
Las opciones ahora se gestionan desde el
.ts
, de forma escalable. -
Podemos cambiar las opciones fácilmente o cargarlas desde un API más adelante.
-
El template está más limpio, sin duplicación.
Paso 4: Manejar selección múltiple con checkboxes
Queremos que:
-
Cada vez que se seleccione o deseleccione una opción, actualicemos un array.
-
El array contenga los
value
de las opciones seleccionadas. -
Usemos
console.log()
para mostrar el estado en tiempo real.
¿Cómo lo haremos?
-
Creamos
selected: string[] = []
en el componente. -
Usamos
(change)
en cada checkbox para manejar la selección. -
Usamos
[checked]
para marcar el estado del checkbox. -
Imprimimos en consola cada vez que cambia la lista.
1. Agrega el estado y función en el .ts
selected: string[] = [];
toggleSelection(value: string): void {
if (this.selected.includes(value)) {
this.selected = this.selected.filter(v => v !== value);
} else {
this.selected.push(value);
}
console.log('Seleccionadas:', this.selected);
}
2. Actualiza el input
en el HTML
Modifica el input dentro del *ngFor
así:
<input
type="checkbox"
[checked]="selected.includes(option.value)"
(change)="toggleSelection(option.value)"
/>
Resultado
Ahora tu componente:
-
Permite seleccionar múltiples opciones.
-
Guarda la selección actualizada en
this.selected
. -
Muestra el array actualizado en consola cada vez que haces clic.
Cierre del post:
🎯 ¿Qué hicimos?
Construimos el mismo componente multiselect dropdown visualmente consistente en:
Framework | Enfoque | Lenguaje | Estado | JSX / Template | Observaciones |
---|---|---|---|---|---|
React | Hooks (useState , useEffect ) |
TypeScript | useState |
JSX | Familiar y flexible. Control explícito. |
Vue 3 | Composition API + ref() + watch |
TypeScript | ref , watch |
Plantilla declarativa | Reactividad clara y directa. Fácil binding. |
Svelte | Variables reactivas (let , $: ) |
TypeScript | Local vars + auto-reactividad | Template HTML puro | Sintaxis más limpia y mínima. Muy ergonómico. |
Angular | Component Class + *ngIf + (change) |
TypeScript | Clases + propiedades | Template estructurado | Verboso pero robusto. Ideal en equipos grandes. |
¿Qué aprendimos?
-
Todos los frameworks modernos permiten construir componentes dinámicos y accesibles.
-
Aunque el resultado visual es el mismo, cada ecosistema tiene su propio “ritmo”:
-
React son ideales si te gusta el control imperativo y JSX.
-
Vue y Svelte son más declarativos y expresivos.
-
Angular prioriza estructura, reglas y escalabilidad.
-
¿Cuál fue más simple?
-
En cuanto a cantidad de código y claridad inmediata, Svelte y Vue 3 se sintieron más livianos.
-
React ofrecieron control fino y granularidad, ideales para lógica compleja.
-
Angular fue el más verboso, pero también el más estricto y mantenible para proyectos grandes.
¿Dónde usar este patrón?
Un componente como este es útil en:
-
Formularios de filtro avanzados
-
Paneles de administración
-
Dashboards
-
Apps móviles con diseño adaptativo
Conclusión
Construir un componente funcional, accesible y visualmente uniforme en diferentes frameworks es una excelente forma de:
-
Aprender sus fortalezas y diferencias
-
Comparar enfoques reactivos
-
Evaluar la curva de entrada y el esfuerzo de mantenimiento
Como desarrolladores, saber trabajar en más de un entorno nos hace más versátiles y estratégicos.
-- ¿Quieres recibir mi newsletter? --
No te pierdas de aprender:
Mi newsletter mensual viene con una dosis de inspiración, recursos para descargar, consejos de desarrollo rápidos y los mismos recursos que aprendo.