@padawanstrainer/select-multiple
v1.0.2
Published
Componente HTML de tipo Select de selección simple o múltiple, con un campo de búsqueda para filtrar los valores de los options
Downloads
264
Maintainers
Readme
SELECT MULTIPLE
Componente HTML de tipo Select que permite la selección de múltiples opciones, con un campo de búsqueda (input de tipo text) para filtrar los valores del select.
ToC:
- Instalación
- Implementación
- Agregar el buscador de opciones
- Agregar una opción vacía
- Mostrar el texto del option y su value
- Aplicar estilos a los elementos
- Limitaciones y pendientes
Instalación
🔹 Para un proyecto node / vite (o similar)
Para instalar el componente como módulo de node (en un proyecto que ejecute servidor de node), ejecutar en la consola del proyecto el comando:
npm install @padawanstrainer/select-multiple
Y hacer el import del componente en el archivo main.js de tu aplicación (o el nombre que tenga tu archivo principal), haciendo un:
import '@padawanstrainer/select-multiple'
🔹 Como un módulo de ES, sin usar npm install
Si no se quiere instalar por medio de npm, clonar o descargar el proyecto desde el repositorio https://github.com/padawanstrainer/select-multiple.
Copiar el archivo main.js
en el directorio de su preferencia e importarlo con un script de tipo module
.
Imaginando que has copiado el archivo main.js
a tu directorio assets/js/select_multiple/main.js
, debería incluirse el siguiente archivo:
<script type="module" src="/assets/js/select_multiple/main.js"></script>
🔹 Directamente desde CDN
Si no se quiere descargar el proyecto desde el repositorio de GitHub y tampoco se planea utilizar el proyecto como un módulo de node, se puede insertar directamente el script desde el CDN ubicado en https://unpkg.com/@padawanstrainer/select-multiple.
También debe ser un script de tipo módulo.
<script type="module" src="https://unpkg.com/@padawanstrainer/select-multiple"></script>
Esto ejecutará la versión más actual del script.
Si se necesita una versión en especial, indicarlo luego del nombre del paquete con un arroba y la versión a usar:
<script type="module" src="https://unpkg.com/@padawanstrainer/[email protected]"></script>
Por cualquiera de las tres vías, el componente será registrado en el DOM para poder usarse como etiqueta en el HTML.
Veamos cómo lo podemos personalizar.
Implementación
Insertar en el HTML, la etiqueta:
<select-multiple></select-multiple>
El atributo name
indica el nombre que tendrá el control al ser enviado con el formulario (si no se indica este atributo, se ignorará el envío del control al endpoint que procese la información).
El atributo label
indica el texto que aparecerá en el select mientras no se haya elegido alguna de sus opciones.
Adentro de la misma insertar etiquetas <option></option>
con su respectivo value
y texto interno.
Tal como sucede con la etiqueta nativa select
, si no se especifica el atributo value
, se tomará el texto interno de la etiqueta.
La opción (u opciones) que deba estar marcada por defecto, deberá tener el atributo selected
.
Ejemplo:
<select-multiple name="pais" label="Elija su nacionalidad">
<option value="ar">Argentina</option>
<option value="bo">Bolivia</option>
<option value="br">Brasil</option>
<option value="ch">Chile</option>
<option value="py">Paraguay</option>
<option value="uy">Uruguay</option>
</select-multiple>
Esto renderizará este componente:
Como vía alternativa, se puede indicar en la etiqueta select-multiple
, el atributo value
que se usará para marcar la opción seleccionada.
Ejemplo:
<select-multiple name="pais" label="Elija su nacionalidad" value="ch">
<option value="ar">Argentina</option>
<option value="bo">Bolivia</option>
<option value="br">Brasil</option>
<option value="ch">Chile</option>
<option value="py">Paraguay</option>
<option value="uy">Uruguay</option>
</select-multiple>
Que usará ese valor para marcar la opción pre-seleccionada:
Si se quiere crear un control de selección múltiple, respetando el aspecto de dropdown, solo se necesita agregar el atributo multiple
.
Esto permitirá tildar más de una opción y se agregará al final del texto del label un contador con la cantidad de opciones elegidas.
En el caso del select
que tenga el atributo multiple
, se pueden definir tantas opciones como sean necesarias con el atributo selected
, o indicar en el atributo value
todos los valores separados por coma.
<select-multiple name="pais" multiple label="Elija sus destinos" value="ch,uy">
<option value="ar">Argentina</option>
<option value="bo">Bolivia</option>
<option value="br">Brasil</option>
<option value="ch">Chile</option>
<option value="py">Paraguay</option>
<option value="uy">Uruguay</option>
</select-multiple>
En este caso, las dos opciones (delimitadas por la coma), serán seleccionadas por defecto:
Esto no inclue el campo de búsqueda, para habilitarlo hace falta indicar otras propiedades de tipo data-attributes
.
Y dado que este control será un elemento de formulario, se lo puede deshabilitar mediante el atributo disabled
:
<select-multiple name="pais" multiple label="Elija sus destinos" disabled>
<option value="ar">Argentina</option>
<option value="bo">Bolivia</option>
<option value="br">Brasil</option>
<option value="ch">Chile</option>
<option value="py">Paraguay</option>
<option value="uy">Uruguay</option>
</select-multiple>
Este atributo no solo impedirá la interacción con el componente, sino que omitirá su envío al action del formulario.
Cabe destacar que este atributo se puede manipular desde Javascript como los demás controles de formulario.
En este supuesto, para Javascript disabled
es una propiedad booleana, aceptando los valores true para deshabilitar el componente, false para habilitarlo.
const sm = document.querySelector('select-multiple');
sm.disabled = true; //control deshabilitado
/* resto de la lógica */
sm.disabled = false; //control shabilitado
/* Toggle de estado */
document.querySelector('my-button')
.addEventListener('click', e => {
sm.disabled = ! sm.disabled;
} );
Habilitar el buscador
Ya sea un select simple o múltiple, agregar el atributo data-search
para habilitar el filtro de opciones.
Si además se le pasa un valor, aparece por delante del input para filtrar las opciones.
Ejemplo:
<select-multiple name="pais" label="Elija su nacionalidad" data-search="Filtrar país">
<option value="ar">Argentina</option>
<option value="bo">Bolivia</option>
<option value="br">Brasil</option>
<option value="ch">Chile</option>
<option value="py">Paraguay</option>
<option value="uy">Uruguay</option>
</select-multiple>
Generando el siguiente output:
El buscador no diferencia mayúsculas de minúsculas y compara contra el value
de cada option, así como su texto interno.
Si una búsqueda no coincide con ninguna entrada no se mostrará ninguna opción.
Agregar una opción "vacía"
Para agregar una opción que represente a "niguna seleccionada", indicar un valor para el atributo data-null
que agregará una nueva opción con el valor del atributo como texto visible del option.
Si además se indica el atibuto data-null-value
, éste será el valor usado al envíar el formulario (caso contrario se mandará el texto indicado en el atributo data-null
).
Acepta el envío de una cadena de texto vacía, que llegará como ''
.
Ejemplo:
<select-multiple name="pais" label="Elija su nacionalidad" data-search="Filtrar país" data-null="Ninguna opción" data-null-value="">
<option value="ar">Argentina</option>
<option value="bo">Bolivia</option>
<option value="br">Brasil</option>
<option value="ch">Chile</option>
<option value="py">Paraguay</option>
<option value="uy">Uruguay</option>
</select-multiple>
Esto generará la siguiente opción extra:
IMPORTANTE
En el select con atributo multiple
se ignora, aunque se lo indique explícitamente, el atributo data-null
, ya que al poderse deseleccionar todas las opciones, no tendría sentido agregar una opción que confunda al usuario final (porque habria que elegir esta nueva opción para no estar eligiendo nada).
No obstante el atributo data-value-null
es el valor que se enviará si no se seleccionó nada, de no estar definido se manda una cadena de texto vacía.
Mostrar text y value
Si se agrega el atributo data-value
(que no es lo mismo que el atributo value
que define las opciones seleccionadas), se antepone al texto de cada opción (salvo al de ninguna opción seleccionada) un label con el value de dicha opción.
Este atributo puede ser útil en los casos que el value también pueda representar algo para el usuario final de la página, a fin de poder ver ambos valores.
No requiere valor, con solo indicar el atributo, se habilita la funcionalidad.
Ejemplo:
<select-multiple name="pais" label="Elija su nacionalidad" data-search="Filtrar país" data-value>
<option value="ar">Argentina</option>
<option value="bo">Bolivia</option>
<option value="br">Brasil</option>
<option value="ch">Chile</option>
<option value="py">Paraguay</option>
<option value="uy">Uruguay</option>
</select-multiple>
El cual generará este control de formulario:
Claro que podríamos tener una opción con un value demasiado largo que nos rompa visualmente el resto del componente, como por ejemplo:
<option value="supercalifragilisticoespialidoso">Super value</option>
En este caso, el value de las opciones tomará el valor más largo generando esta atrocidad visual:
En consecuencia, de ser necesario, se puede definir el ancho máximo para ese label, y todo lo que exceda ese ancho será truncado con puntos suspensivos (ellipsis).
Esto se hace por medio del atributo data-value-width
que espera recibir un valor numérico que será traducido a la unidad ch (en una fuente monoespaciada, serían la cantidad de caracteres/chars) en la muestra final, en una fuente NO monoespaciada, puede no representar el mismo ancho.
Ejemplo:
<select-multiple name="pais" label="Elija su nacionalidad" data-search="Filtrar país" data-value data-value-width="5">
<option value="ar">Argentina</option>
<option value="bo">Bolivia</option>
<option value="br">Brasil</option>
<option value="ch">Chile</option>
<option value="py">Paraguay</option>
<option value="uy">Uruguay</option>
</select-multiple>
El cual generará este control de formulario:
Este atributo se ignorará en dos casos:
- Si el atributo no tiene valor.
- Si el valor del
data-value-width
es mayor que el ancho del texto más largo (aplicando el ancho del texto más largo).
Estilar el componente
Dado que el componente está encapsulado, no se puede acceder a la estructura de etiquetas internas para estilizarlas (esto también garantiza que no se rompa el componente por algún conflicto con una hoja de estilos externa). Por lo cual, las propiedades que se pueden modificar ya están predefinidas como variables CSS (o mejor dicho, Custom properties).
Como sucede con cualquier etiqueta HTML, se puede aplicar estilos creando una regla para la etiqueta select-multiple
, o asignarles un class
o id
.
En este documento, se ejemplificará accediéndola por nombre de etiqueta.
El select-multiple
está formado por 3 elementos:
Este es un listado de las opciones formateables:
🔹 El dropdown
La familia y el tamaño tipográfico del combo y sus opciones, es heredada del último elemento padre que tenga una fuente definida.
Pero se puede indicar una fuente puntual para el combo-header con la propiedad --sm-font
, que espera un valor válido para la familia tipográfica (uno o varios nombres separados por coma).
El border que rodea tanto al combo-header como al combo-body se indica con la propiedad --sm-border
que acepta cualquier notación de color válida.
El color de fondo del combo-header se indica con la propiedad --sm-bg-color
, que acepta cualquier notación de color. Este valor no se propagará al combo-body ni a los combo-options.
Mientras que el ícono del drop-down (la fecha para abajo) también se puede customizar, por medio de la propiedad --sm-bg-icon
, que espera una url( )
con la ruta a la imagen a usar como ícono.
Por defecto las imágenes a usar como ícono del dropdown, tiene un alto de .5lh
(la mitad del valor indicado como line-height), se puede modificar con la propiedad --sm-bg-size
que acepta cualquier unidad que se pueda usar como background-size (en px, lh, ch, em, etc).
Y en los casos que la cantidad de opciones supere el alto máximo del combo-body se mostrará una barra de scroll, cuyos colores también se pueden definir con las propiedades --sm-scrollbar-front
que aplica al elemento de frente que se desplaza con el scroll y --sm-scrollbar-back
que es color de fondo de todo el alto del scrollbar (el elemento que no se mueve junto al scroll). Acepta cualquier notación de color válida.
Este es un ejemplo de las propiedades explicadas:
select-multiple{
/* Aplica solo para el combo-header */
--sm-font: 'Poppins', sans-serif;
/* Combo-header y options */
font-family: 'Vivaldi', cursive;
--sm-border: #1B4D78;
--sm-bg-color: #286090;
--sm-bg-icon: url('arrow.png');
--sm-bg-size: 1.2em;
--sm-color: white;
--sm-scrollbar-front: #FFFFC9;
--sm-scrollbar-back: #1A3146;
}
Que se mostraría así:
🔹 Las opciones
Al igual que sucede con el combo-header, las opciones aceptan definir su familia tipográfica, independiente del valor del combo.
Esto se hace con la propiedad --sm-options-font
, que acepta el listado de familias tipográficas a aplicar.
De no estar definida, heredará la tipografía del último elemento que tenga un valor explícito o usará la fuente por defecto del navegador.
El tamaño de la fuente se indica con la propiedad --sm-options-size
.
Y al igual que sucede con el combo-header se puede indicar el color de fondo y color de texto con las propiedades --sm-options-bg
y --sm-options-color
, respectivamente.
Por cada opción se muestra un border-bottom
, cuyo color se puede definir con la propiedad --sm-options-border
.
Y los combo-options aceptan el estado :hover
, en este caso se puede cambiar el color de fondo y de texto de la opción con los atributos --sm-options-hover-color
y --sm-options-hover-bg
, respectivamente.
Si agregamos estos estilos al combo:
select-multiple{
--sm-options-font: 'Impact', sans-serif;
--sm-options-size: 25px;
--sm-options-bg: #F0F0BC;
--sm-options-color: #7C0305;
--sm-options-border: transparent;
--sm-options-hover-bg: #480A2C;
--sm-options-hover-color: #7CE0A2;
}
Se vería de esta manera:
`
🔹 Los íconos de la opciones
Al seleccionar una opción del menú desplegable, se muestra el ícono de un tilde de check ✓
.
Esta imagen se puede cambiar con la propiedad --sm-options-checked
que espera una url( )
que apunte a la imagen a usar como estado :checked.
Adicionalmente, se puede indicar un ícono para las opciones que no fueron seleccionadas, por medio de la propiedad --sm-options-unchecked
que también espera una url( )
.
Y, dado que al pasar el mouse por encima de una opción no seleccioanda, su ícono podría no hacer suficiente contraste con el color de fondo, se puede cambiar la imagen en el estado :hover con el atributo --sm-options-unchecked-hover
Entonces, si a los combo-options le damos estos estilos:
select-multiple{
--sm-options-size: 20px;
--sm-options-bg-color: lightyellow;
--sm-options-checked: url(check_si.svg);
--sm-options-unchecked: url(check_no.svg);
--sm-options-unchecked-hover: url(check_no_negro.svg);
}
Veremos este menú desplegable:
🔹 El valor visible en la opción
Si habilitamos la muestra de los values por delante del texto de la opción, podemos indicar el color del texto con la propiedad --sm-options-value-color
.
Y el color del texto, cuando se pase el mouse por encima de una opción, se define con la propiedad --sm-options-value-hover-color
.
Estos estilos:
select-multiple{
--sm-options-value-color: red;
--sm-options-value-hover-color: yellow;
}
Genera este menú desplegable.
🔹 El filtro/buscador de opciones
Si se habilita el filtro de búsqueda de opciones, se pueden customizar los estilos principales del buscador.
Esto involucra al color de fondo de la barra de búsqueda con la propiedad --sm-search-bg
, el color del texto con la propiedad --sm-search-color
y si se ha definido un valor para el texto del data-search
y se quiere usar un color distinto, se lo puede indicar con el atributo --sm-search-label-color
.
Tal como se puede ver en el ejemplo a continuación:
select-multiple{
--sm-search-bg: #460848;
--sm-search-color: #00FF12;
--sm-search-label-color: #F5EA9B;
}
Que afectará al select-multiple de esta manera:
🔹 CSS específico para las opciones seleccionadas
Finalmente, al tener una opción seleccionada, no solo se puede modificar el ícono que se muestra, sino que podemos cambiar todas las propiedades ya declaradas para las opciones.
El color de fondo y de texto de una opción seleccionada, se definen con las propiedades --sm-options-checked-bg
y --sm-options-checked-color
, respectivamente.
Y si se tiene habilitada la muestra de los values, el color para la el estado :checked se define con la propiedad --sm-options-checked-value-color
.
Por ejemplo con estos valores:
select-multiple{
--sm-options-checked-bg: #FFCE6C;
--sm-options-checked-color: #2150D1;
--sm-options-checked-value-color: #FFFFFF;
}
Tendríamos esta salida visual:
Y lógicamente, todos los valores pueden modificarse al pasar el mouse por encima.
El color de fondo y de texto se definen por medio de los atributos --sm-options-checked-hover-bg
y --sm-options-checked-hover-color
, respectivamente.
El color del value visible se define con la propiedad --sm-options-checked-value-hover-color
.
Y dado que el ícono puede no hacer suficiente contraste con el nuevo esquema de colores, si se necesita cambiar el archivo se puede hacer con el atributo --sm-options-checked-hover-icon
que espera una url( )
hacia la imagen a usar y, de no indicarse, seguirá usando el ícono de la opción seleccionada por defecto.
Con lo cual, podrías sobreescribir todos los valores de las opciones seleccioandas en el estado :hover
, aplicando estos estilos.
select-multiple{
--sm-options-checked-hover-bg: #D39008;
--sm-options-checked-hover-color: black;
--sm-options-checked-hover-value-color: black;
--sm-options-checked-hover-icon: url(check_si_blanco.svg);
}
Y nuestro combo se vería de esta manera:
Limitaciones y pendientes
En el caso de ser una etiqueta de selección múltiple, el componente enviará como valor todos los value de las opciones seleccionadas en un único string delimitado por comas.
En consecuencia, en el lenguaje que se deba procesar la información, si se requiere cada valor por separado, se deberá usar el método correspondiente para separar el string por comas (sea split
, strsplit
, explode
, etc).
La versión actual no permite la agupación visual de opciones como sucede con la etiqueta <optgroup></optgroup>
de HTML. Sin embargo está en mi intención el ofrecer una solución para poder jerarquizar mejor la información del menú desplegable.
Este componente se ofrece sin fines de lucro, con la intención de facilitarle el trabajo a quienes ya tuvieros esta misma pelea y no encontraron aún una solución para poder elegir múltiples opciones desde un dropdown sin tener que expandir por defecto las opciones.
Esto significa que pude haber cometido algún error de programación que no esté viendo o no me haya saltado en mis casos de usos habituales, o que la semana que viene la W3C o WHATWG saquen su propia implementación nativa del select-multiple, haciendo este script obsoleto.
Pero si hasta entonces, este CustomElement te sirvió de algo, mi misión está cumplida.
Te deseo lo mejor en tus proyectos y nunca dejes de aprender y desafiarte.
♞