List Picker
<gstock-list-picker>
|
GstockListPicker
Ejemplos
Básico
El componente List Picker permite seleccionar elementos de una lista con funcionalidad de búsqueda integrada.
<gstock-list-picker label="Selecciona una fruta"></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('gstock-list-picker');
picker.items = [
{ value: '1', label: 'Manzana' },
{ value: '2', label: 'Banana' },
{ value: '3', label: 'Naranja' },
{ value: '4', label: 'Fresa' },
{ value: '5', label: 'Uva' },
];
});
</script>
Selección Múltiple
Utilice el atributo multiple para habilitar la selección de múltiples elementos.
<gstock-list-picker id="multiple-picker" label="Programming languages" multiple></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#multiple-picker');
picker.items = [
{ value: '1', label: 'JavaScript' },
{ value: '2', label: 'TypeScript' },
{ value: '3', label: 'Python' },
{ value: '4', label: 'Java' },
{ value: '5', label: 'C#' },
{ value: '6', label: 'Go' },
{ value: '7', label: 'Rust' },
{ value: '8', label: 'PHP' },
];
});
</script>
Tamaños
Utilice el atributo size para cambiar el tamaño de los controles internos. Para controlar la altura del componente, use la custom property --height (por defecto fit-content, que se adapta al contenido).
<div class="sizes-demo">
<div>
<gstock-list-picker id="small-picker" label="Small (200px)" size="small" class="height-small"></gstock-list-picker>
</div>
<div>
<gstock-list-picker id="medium-picker" label="Medium (350px)" size="medium" class="height-medium"></gstock-list-picker>
</div>
<div>
<gstock-list-picker id="large-picker" label="Large (500px)" size="large" class="height-large"></gstock-list-picker>
</div>
</div>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const items = [
{ value: '1', label: 'Item 1' },
{ value: '2', label: 'Item 2' },
{ value: '3', label: 'Item 3' },
{ value: '4', label: 'Item 4' },
{ value: '5', label: 'Item 5' },
];
document.querySelector('#small-picker').items = items;
document.querySelector('#medium-picker').items = items;
document.querySelector('#large-picker').items = items;
});
</script>
<style>
.sizes-demo {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--gstock-space-gap-lg);
}
.height-small {
--height: 200px;
}
.height-medium {
--height: 350px;
}
.height-large {
--height: 500px;
}
</style>
Con Valores Preseleccionados
Puede establecer valores preseleccionados mediante el atributo value.
<div class="preselected-demo">
<gstock-list-picker label="Selección Simple" id="preselected-single" value="2"></gstock-list-picker>
<gstock-list-picker label="Selección Múltiple" id="preselected-multiple" multiple></gstock-list-picker>
</div>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const items = [
{ value: '1', label: 'Rojo' },
{ value: '2', label: 'Verde' },
{ value: '3', label: 'Azul' },
{ value: '4', label: 'Amarillo' },
];
document.querySelector('#preselected-single').items = items;
const multiplePicker = document.querySelector('#preselected-multiple');
multiplePicker.items = items;
multiplePicker.value = ['1', '3'];
});
</script>
<style>
.preselected-demo {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: var(--gstock-space-gap-lg);
}
.preselected-demo h4 {
margin-top: 0;
margin-bottom: var(--gstock-space-gap-sm);
color: var(--gstock-color-text-primary);
}
</style>
Placeholder Personalizado
Utilice el atributo placeholder para personalizar el texto del buscador.
<gstock-list-picker id="placeholder-picker" placeholder="Buscar ciudades..."></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#placeholder-picker');
picker.items = [
{ value: '1', label: 'Madrid' },
{ value: '2', label: 'Barcelona' },
{ value: '3', label: 'Valencia' },
{ value: '4', label: 'Sevilla' },
{ value: '5', label: 'Bilbao' },
];
});
</script>
Label y Help Text
Utilice los atributos label y help-text para añadir contexto al componente.
<gstock-list-picker id="list-picker-label" label="Selecciona un país" help-text="Elige tu país de residencia" placeholder="Buscar países..." size="medium"></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const listPicker = document.querySelector('#list-picker-label');
const countries = [
{ value: 'es', label: 'España' },
{ value: 'fr', label: 'Francia' },
{ value: 'de', label: 'Alemania' },
{ value: 'it', label: 'Italia' },
{ value: 'pt', label: 'Portugal' },
{ value: 'uk', label: 'Reino Unido' },
{ value: 'us', label: 'Estados Unidos' },
{ value: 'ca', label: 'Canadá' },
{ value: 'mx', label: 'México' },
{ value: 'br', label: 'Brasil' },
{ value: 'ar', label: 'Argentina' },
{ value: 'cl', label: 'Chile' },
];
listPicker.items = countries;
});
</script>
Label y Help Text con Slots
También puede usar slots para personalizar el label y help text con HTML.
<gstock-list-picker id="list-picker-slots" placeholder="Buscar idiomas..." size="medium">
<span slot="label" class="custom-label">
<gstock-icon name="globe"></gstock-icon>
Idiomas preferidos
</span>
<span slot="help-text" class="custom-help">
<gstock-icon name="info"></gstock-icon>
Puedes seleccionar múltiples idiomas
</span>
</gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const listPicker = document.querySelector('#list-picker-slots');
const languages = [
{ value: 'es', label: 'Español' },
{ value: 'en', label: 'Inglés' },
{ value: 'fr', label: 'Francés' },
{ value: 'de', label: 'Alemán' },
{ value: 'it', label: 'Italiano' },
{ value: 'pt', label: 'Portugués' },
{ value: 'zh', label: 'Chino' },
{ value: 'ja', label: 'Japonés' },
{ value: 'ko', label: 'Coreano' },
{ value: 'ar', label: 'Árabe' },
];
listPicker.items = languages;
listPicker.multiple = true;
});
</script>
<style>
.custom-label {
display: flex;
align-items: center;
gap: var(--gstock-space-100);
color: var(--gstock-color-text-primary);
font-weight: var(--gstock-typography-font-weight-semibold);
}
.custom-help {
display: flex;
align-items: center;
gap: var(--gstock-space-100);
color: var(--gstock-color-text-secondary);
}
</style>
Validación en Formularios
El componente soporta validación nativa de formularios HTML con el atributo required.
<form class="form-container">
<gstock-list-picker name="country" label="País de residencia" help-text="Este campo es obligatorio" placeholder="Selecciona un país..." required size="medium"></gstock-list-picker>
<gstock-button type="submit" variant="primary">Enviar</gstock-button>
</form>
<div id="result" class="result-container"></div>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const form = document.querySelector('form');
const listPicker = document.querySelector('gstock-list-picker');
const result = document.querySelector('#result');
const countries = [
{ value: 'es', label: 'España' },
{ value: 'fr', label: 'Francia' },
{ value: 'de', label: 'Alemania' },
{ value: 'it', label: 'Italia' },
{ value: 'pt', label: 'Portugal' },
{ value: 'uk', label: 'Reino Unido' },
{ value: 'us', label: 'Estados Unidos' },
{ value: 'ca', label: 'Canadá' },
{ value: 'mx', label: 'México' },
{ value: 'br', label: 'Brasil' },
];
listPicker.items = countries;
form.addEventListener('submit', event => {
event.preventDefault();
if (!listPicker.checkValidity()) {
listPicker.reportValidity();
return;
}
const formData = new FormData(form);
const selectedCountry = formData.get('country');
if (selectedCountry) {
const countryLabel =
countries.find(c => c.value === selectedCountry)?.label || selectedCountry;
result.innerHTML = `
<div class="success-message">
✓ Formulario enviado correctamente<br>
País seleccionado: <strong>${countryLabel}</strong>
</div>
`;
}
});
listPicker.addEventListener('gstock-change-event', () => {
result.innerHTML = '';
});
});
</script>
<style>
.form-container {
display: flex;
flex-direction: column;
gap: var(--gstock-space-gap-xl);
}
.result-container {
margin-top: var(--gstock-space-gap-xl);
}
.success-message {
padding-block: var(--gstock-space-padding-block-lg);
padding-inline: var(--gstock-space-padding-inline-lg);
background-color: var(--gstock-color-background-success);
color: var(--gstock-color-text-success);
border-radius: var(--gstock-border-radius-md);
border: var(--gstock-border-width) solid var(--gstock-color-border-success);
}
</style>
Items Deshabilitados
Los items pueden estar deshabilitados individualmente.
<gstock-list-picker id="disabled-items-picker"></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#disabled-items-picker');
picker.items = [
{ value: '1', label: 'Disponible' },
{ value: '2', label: 'No disponible', disabled: true },
{ value: '3', label: 'Disponible' },
{ value: '4', label: 'Agotado', disabled: true },
{ value: '5', label: 'Disponible' },
];
});
</script>
Componente Deshabilitado
Utilice el atributo disabled para deshabilitar todo el componente.
<gstock-list-picker id="disabled-picker" disabled></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#disabled-picker');
picker.items = [
{ value: '1', label: 'Item 1' },
{ value: '2', label: 'Item 2' },
{ value: '3', label: 'Item 3' },
];
});
</script>
Búsqueda
El componente incluye un buscador integrado que filtra los items localmente.
<gstock-list-picker id="search-picker" placeholder="Buscar países..."></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#search-picker');
picker.items = [
{ value: '1', label: 'España' },
{ value: '2', label: 'Francia' },
{ value: '3', label: 'Italia' },
{ value: '4', label: 'Alemania' },
{ value: '5', label: 'Portugal' },
{ value: '6', label: 'Reino Unido' },
{ value: '7', label: 'Países Bajos' },
{ value: '8', label: 'Bélgica' },
{ value: '9', label: 'Suiza' },
{ value: '10', label: 'Austria' },
];
});
</script>
Scroll Virtual con Muchos Items
El componente utiliza scroll virtual para manejar eficientemente grandes cantidades de datos.
<gstock-list-picker id="virtual-scroll-picker" multiple placeholder="Buscar en 1000 items..."></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#virtual-scroll-picker');
picker.items = Array.from({ length: 1000 }, (_, i) => ({
value: `${i + 1}`,
label: `Item ${i + 1}`,
}));
});
</script>
<style>
gstock-list-picker {
--height: 400px;
}
</style>
Modo Asíncrono
Utilice el atributo async para cargar datos desde un servidor. El componente emitirá el evento gstock-search-event cada vez que el usuario escriba en el buscador.
<gstock-list-picker id="async-picker" async debounce-delay="300" placeholder="Buscar usuarios (simulado)..."></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#async-picker');
const allUsers = [
{ value: '1', label: 'Ana García' },
{ value: '2', label: 'Juan Martínez' },
{ value: '3', label: 'María López' },
{ value: '4', label: 'Carlos Rodríguez' },
{ value: '5', label: 'Laura Fernández' },
{ value: '6', label: 'Pedro Sánchez' },
{ value: '7', label: 'Carmen Jiménez' },
{ value: '8', label: 'David Torres' },
];
picker.addEventListener('gstock-search-event', e => {
const query = e.detail.search.toLowerCase();
picker.loading = true;
setTimeout(() => {
if (query) {
picker.items = allUsers.filter(user => user.label.toLowerCase().includes(query));
} else {
picker.items = allUsers;
}
picker.loading = false;
}, 500);
});
picker.items = allUsers;
});
</script>
Eventos
El componente emite eventos cuando cambia la selección.
Log de Eventos:
<div>
<gstock-list-picker id="events-picker" multiple></gstock-list-picker>
<div class="event-log">
<h4>Log de Eventos:</h4>
<div id="event-output"></div>
</div>
</div>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#events-picker');
const output = document.querySelector('#event-output');
picker.items = [
{ value: '1', label: 'Option A' },
{ value: '2', label: 'Option B' },
{ value: '3', label: 'Option C' },
{ value: '4', label: 'Option D' },
];
function logEvent(eventName, detail) {
const entry = document.createElement('div');
entry.className = 'event-entry';
entry.innerHTML = `<strong>${eventName}</strong>: ${JSON.stringify(detail)}`;
output.insertBefore(entry, output.firstChild);
if (output.children.length > 5) {
output.removeChild(output.lastChild);
}
}
picker.addEventListener('gstock-change-event', () => {
logEvent('gstock-change-event', picker.value);
});
picker.addEventListener('gstock-clear-event', () => {
logEvent('gstock-clear-event', 'Selección limpiada');
});
});
</script>
<style>
.event-log {
margin-top: var(--gstock-space-gap-lg);
padding: var(--gstock-space-padding-md);
background-color: var(--gstock-color-background-secondary);
border-radius: var(--gstock-border-radius-md);
}
.event-log h4 {
margin-top: 0;
margin-bottom: var(--gstock-space-gap-sm);
color: var(--gstock-color-text-primary);
}
#event-output {
font-family: monospace;
font-size: 0.875rem;
}
.event-entry {
padding: var(--gstock-space-padding-xs);
margin-bottom: var(--gstock-space-gap-xs);
background-color: var(--gstock-color-background-primary);
border-radius: var(--gstock-border-radius-sm);
}
.event-entry strong {
color: var(--gstock-color-text-primary);
}
</style>
Límite de Chips Visibles
Utilice el atributo max-chips-visible para controlar cuántos chips se muestran en el footer antes de colapsar.
Máximo 2 chips visibles:
<div>
<h4>Máximo 2 chips visibles:</h4>
<gstock-list-picker id="chips-limit-picker" multiple max-chips-visible="2"></gstock-list-picker>
</div>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#chips-limit-picker');
picker.items = [
{ value: '1', label: 'Tag 1' },
{ value: '2', label: 'Tag 2' },
{ value: '3', label: 'Tag 3' },
{ value: '4', label: 'Tag 4' },
{ value: '5', label: 'Tag 5' },
];
picker.value = ['1', '2', '3', '4', '5'];
});
</script>
<style>
h4 {
margin-top: 0;
margin-bottom: var(--gstock-space-gap-sm);
color: var(--gstock-color-text-primary);
}
</style>
Sin Seleccionar Todo
Utilice show-select-all="false" para ocultar el checkbox de seleccionar todo en modo múltiple.
<gstock-list-picker id="no-select-all-picker" multiple show-select-all="false"></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#no-select-all-picker');
picker.items = [
{ value: '1', label: 'Item 1' },
{ value: '2', label: 'Item 2' },
{ value: '3', label: 'Item 3' },
{ value: '4', label: 'Item 4' },
];
});
</script>
Slot Personalizado para Estado Vacío
Puede personalizar el mensaje cuando no hay resultados usando el slot empty.
No se encontraron resultados
Intenta con otros términos de búsqueda
<gstock-list-picker search="xyz">
<div slot="empty" class="custom-empty">
<gstock-icon name="search"></gstock-icon>
<p>No se encontraron resultados</p>
<p class="empty-hint">Intenta con otros términos de búsqueda</p>
</div>
</gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('gstock-list-picker');
picker.items = [
{ value: '1', label: 'Apple' },
{ value: '2', label: 'Banana' },
{ value: '3', label: 'Cherry' },
];
});
</script>
<style>
.custom-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: var(--gstock-space-padding-2xl);
text-align: center;
}
.custom-empty gstock-icon {
font-size: 3rem;
opacity: 0.3;
margin-bottom: var(--gstock-space-gap-md);
}
.custom-empty p {
margin: var(--gstock-space-gap-xs) 0;
color: var(--gstock-color-text-primary);
}
.empty-hint {
font-size: 0.875rem;
color: var(--gstock-color-text-secondary);
}
</style>
Altura de Item Personalizada
Si necesita items más altos, ajuste el atributo item-height.
<gstock-list-picker id="custom-height-picker" item-height="60"></gstock-list-picker>
<script type="module">
customElements.whenDefined('gstock-list-picker').then(() => {
const picker = document.querySelector('#custom-height-picker');
picker.items = [
{ value: '1', label: 'Item con altura de 60px' },
{ value: '2', label: 'Item con altura de 60px' },
{ value: '3', label: 'Item con altura de 60px' },
{ value: '4', label: 'Item con altura de 60px' },
];
});
</script>