Skip to content

MultiSelect

Visão geral

Permite o usuário pesquisar e selecionar uma opção ou mais em uma lista.

Formato do v-model

⚠️ O v-model recebe e devolve os objetos completos das opções selecionadas — não apenas a chave/id.

Input (options):

json
[
  { "Nome": "Vue.js",     "Id": "vu" },
  { "Nome": "Javascript", "Id": "js" },
  { "Nome": "CSS",        "Id": "css" }
]

Output (modelValue) após selecionar "Javascript":

json
[
  { "Nome": "Javascript", "Id": "js" }
]

Para enviar ao backend, extraia apenas os IDs:

javascript
// ✅ extrair IDs ao montar o payload
const payload = {
  Ids: form.value.Tags.map(t => t.Id)
}

Inicialização: sempre ref([]) — nunca null.

Variações

VariaçãoDescrição
MultiSelectPermite o usuário pesquisar e selecionar uma opção ou mais em uma lista.
ComboBoxPermite o usuário pesquisar e selecionar uma opção em uma lista. Ele também permite o usuário criar uma nova opção

Propriedades

NomeDescriçãoTipoPadrão
id⚠️ obr Define o identificado único(id) que o input irá receberString-
disabledDefine se o campo está desabilitado
labelDefine a label do inputString-
placeholderDefine o placeholder (texto quando não se há nenhuma opção selecionada) do inputString"Selecione"
error-textMensagem de erro quando o campo é inválidoString-
help-textDefine uma mensagem abaixo do campo para fornecer uma ajuda adicionalString-
options*⚠️ obr Define quais serão as opções disponíveis para seleção. Quando for objetos, defina também as propriedades track-by e options-labelArray-
options-keyDefine qual a chave unica em uma lista de objetosString-
options-labelDefine qual a propriedade do Objeto que será exibido no combo. Também pode ser passada uma Function em casos de label customizado (ex: :customLabel="({ id, descricao }) => ``${id} - ${descricao}`)String Function-
group-labelDefine qual a propriedade do objeto será exibida em caso de agrupamento de opçõesString-
group-valuesDefine qual a propriedade do objeto será exibida como 'options' do agrupamentoString-
checkbox-selectorDefine se vai ser utilizado checkbox no layout das options.Booleanfalse
select-allDefine se será exibido o slot de "Selecionar todos".Booleanfalse
selected-on-topDefine se será utilizado a função de agrupar todos os itens selecionados no topo da listagem. Quando utilizado defina também a propriedade options-key.Booleanfalse
custom-label-multipleDefine qual será a label para substituir o padrão x itens selecionadosStringitens selecionados
custom-option-filterPermite passar uma função personalizada para filtrar as opções exibidas conforme o texto digitado pelo usuário.Function -
fetch-optionsFunção (query: string) => Promise<Array> que o componente chama internamente para buscar opções. Quando fornecida, o componente gerencia o estado de loading e as opções buscadas.Function-
lazyQuando true, o fetch só é disparado após o usuário digitar (ideal para tabelas grandes). Quando false, carrega ao abrir o dropdown pela primeira vez.Booleanfalse
min-search-lengthQuantidade mínima de caracteres para disparar o fetch no modo lazy.Number3
debounce-msTempo em milissegundos de debounce entre cada digitação e o disparo do fetch.Number300
fetch-on-mountQuando true, dispara o fetch imediatamente ao montar o componente, sem precisar abrir o dropdown. Útil para componentes encadeados que precisam recarregar ao trocar o pai.
⚠️ Não tem efeito quando lazy=true — no modo lazy nenhum fetch é disparado até o usuário digitar.
Booleanfalse

Playground

PropControle
fetch-options
requer fetch-options
requer lazy=true
requer fetch-options
requer fetch-options
Selecione
modelValue: []
Selecione ou digite
modelValue: []
Clique para exibir o código
vue
<script setup>
import { ref } from 'vue';
import { LxMultiSelect } from '@lde/lxcomponents';

// --- dados estáticos ---
const staticValue = ref([]);
const tecnologias = [
	{ Nome: 'Vue.js', Id: 'vu' },
	{ Nome: 'Javascript', Id: 'js' },
	{ Nome: 'Open Source', Id: 'os' },
	{ Nome: 'CSS', Id: 'css' },
	{ Nome: '.NET', Id: 'net' },
	{ Nome: 'HTML', Id: 'ht' },
	{ Nome: 'TypeScript', Id: 'ts' },
	{ Nome: 'Python', Id: 'py' },
	{ Nome: 'Go', Id: 'go' },
	{ Nome: 'Rust', Id: 'rs' }
];

// --- dados agrupados ---
const groupValue = ref([]);
const stacks = [
	{
		Tipo: 'Front-end',
		Tecs: [
			{ Nome: 'Vue.js', Id: 'vu' },
			{ Nome: 'Javascript', Id: 'js' },
			{ Nome: 'CSS', Id: 'css' },
			{ Nome: 'HTML', Id: 'ht' }
		]
	},
	{
		Tipo: 'Back-end',
		Tecs: [
			{ Nome: '.NET', Id: 'net' },
			{ Nome: 'Java', Id: 'java' }
		]
	}
];

// --- fetch simulado ---
const fetchValue = ref([]);
const fetchOptions = async (query) => {
	await new Promise((r) => setTimeout(r, 400));
	return tecnologias.filter((t) => t.Nome.toLowerCase().includes(query.toLowerCase()));
};

// --- controles ---
const label = ref('Tecnologias');
const placeholder = ref('Selecione');
const helpText = ref('');
const errorText = ref('');
const disabled = ref(false);
const isInvalid = ref(false);
const checkboxSelector = ref(false);
const selectAll = ref(false);
const selectedOnTop = ref(false);
const customLabelMultiple = ref('itens selecionados');

// fetch-specific
const lazy = ref(false);
const minSearchLength = ref(3);
const debounceMs = ref(300);
const fetchOnMount = ref(false);
const useFetch = ref(false);
</script>

<template>
	<!-- playground controls -->
	<table>
		<thead>
			<tr>
				<th style="width: 180px">Prop</th>
				<th>Controle</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td><label class="form-label m-0">label</label></td>
				<td><input v-model="label" type="text" class="form-control" /></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">placeholder</label></td>
				<td><input v-model="placeholder" type="text" class="form-control" /></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">help-text</label></td>
				<td><input v-model="helpText" type="text" class="form-control" /></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">error-text</label></td>
				<td><input v-model="errorText" type="text" class="form-control" /></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">disabled</label></td>
				<td><input v-model="disabled" type="checkbox" class="form-check-input" /></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">is-invalid</label></td>
				<td><input v-model="isInvalid" type="checkbox" class="form-check-input" /></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">checkbox-selector</label></td>
				<td><input v-model="checkboxSelector" type="checkbox" class="form-check-input" /></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">select-all</label></td>
				<td><input v-model="selectAll" type="checkbox" class="form-check-input" /></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">selected-on-top</label></td>
				<td><input v-model="selectedOnTop" type="checkbox" class="form-check-input" /></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">custom-label-multiple</label></td>
				<td><input v-model="customLabelMultiple" type="text" class="form-control" /></td>
			</tr>
			<tr>
				<td colspan="2"><strong>fetch-options</strong></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">usar fetch-options</label></td>
				<td><input v-model="useFetch" type="checkbox" class="form-check-input" /></td>
			</tr>
			<tr>
				<td><label class="form-label m-0">lazy</label></td>
				<td>
					<input v-model="lazy" type="checkbox" class="form-check-input" :disabled="!useFetch" />
					<small v-if="!useFetch" class="text-muted ms-2">requer fetch-options</small>
				</td>
			</tr>
			<tr>
				<td><label class="form-label m-0">min-search-length</label></td>
				<td>
					<input v-model.number="minSearchLength" type="number" min="1" class="form-control" style="width: 80px" :disabled="!useFetch || !lazy" />
					<small v-if="!lazy" class="text-muted ms-2">requer lazy=true</small>
				</td>
			</tr>
			<tr>
				<td><label class="form-label m-0">debounce-ms</label></td>
				<td>
					<input v-model.number="debounceMs" type="number" min="0" step="50" class="form-control" style="width: 80px" :disabled="!useFetch" />
					<small v-if="!useFetch" class="text-muted ms-2">requer fetch-options</small>
				</td>
			</tr>
			<tr>
				<td><label class="form-label m-0">fetch-on-mount</label></td>
				<td>
					<input v-model="fetchOnMount" type="checkbox" class="form-check-input" :disabled="!useFetch || lazy" />
					<small v-if="lazy" class="text-muted ms-2">⚠️ sem efeito quando lazy=true</small>
					<small v-else-if="!useFetch" class="text-muted ms-2">requer fetch-options</small>
				</td>
			</tr>
		</tbody>
	</table>

	<!-- preview: opções estáticas -->
	<div class="row mt-4" v-if="!useFetch">
		<div class="col-12">
			<LxMultiSelect
				v-model="staticValue"
				:label="label"
				:placeholder="placeholder"
				:help-text="helpText"
				:error-text="errorText"
				:disabled="disabled"
				:is-invalid="isInvalid"
				:checkbox-selector="checkboxSelector"
				:select-all="selectAll"
				:selected-on-top="selectedOnTop"
				:custom-label-multiple="customLabelMultiple"
				options-key="Id"
				:options="tecnologias"
				:options-label="({ Nome, Id }) => `${Nome} (${Id})`"
			/>
		</div>
		<div class="col-12 mt-2">
			<strong>modelValue: </strong><small>{{ staticValue }}</small>
		</div>
	</div>

	<!-- preview: fetch simulado -->
	<div class="row mt-4" v-else>
		<div class="col-12">
			<LxMultiSelect
				v-model="fetchValue"
				:label="label"
				:placeholder="placeholder"
				:help-text="helpText"
				:error-text="errorText"
				:disabled="disabled"
				:is-invalid="isInvalid"
				:checkbox-selector="checkboxSelector"
				:select-all="selectAll"
				:selected-on-top="selectedOnTop"
				:custom-label-multiple="customLabelMultiple"
				options-key="Id"
				:options-label="({ Nome, Id }) => `${Nome} (${Id})`"
				:fetch-options="fetchOptions"
				:lazy="lazy"
				:min-search-length="minSearchLength"
				:debounce-ms="debounceMs"
				:fetch-on-mount="fetchOnMount"
			/>
		</div>
		<div class="col-12 mt-2">
			<strong>modelValue: </strong><small>{{ fetchValue }}</small>
		</div>
	</div>

	<!-- preview: agrupado (fixo) -->
	<div class="row mt-4">
		<div class="col-12">
			<LxMultiSelect
				v-model="groupValue"
				label="Exemplo com grupos"
				options-key="Id"
				group-label="Tipo"
				group-values="Tecs"
				:options="stacks"
				:options-label="({ Nome, Id }) => `${Nome} (${Id})`"
				:checkbox-selector="checkboxSelector"
				:disabled="disabled"
			/>
		</div>
		<div class="col-12 mt-2">
			<strong>modelValue: </strong><small>{{ groupValue }}</small>
		</div>
	</div>
</template>

Desenvolvido pelo time Linx Microvix