Components/SearchSelect
Universal Component

SearchSelect

Searchable select input with local filtering, remote search events, and Popover-backed options panel.

This page was migrated by AI, please review carefully

Migration is complete, but please validate against source code and manual review.

SearchSelect

TxSearchSelect combines a text input, local option filtering, optional remote search, and a Popover-backed options panel. Disabled options stay visible but cannot be selected.

The dropdown layer is hosted by TxPopover with full-width reference anchoring and no reference-click toggle.

Basic Usage

SearchSelect

Demo will load when visible.
<script setup lang="ts">
import { ref } from 'vue'

const value = ref<string | number>('')

const options = [
  { value: 'foo', label: 'Foo' },
  { value: 'bar', label: 'Bar' },
  { value: 'baz', label: 'Baz' },
  { value: 'disabled', label: 'Disabled', disabled: true },
]
</script>

<template>
  <div style="display: flex; flex-direction: column; gap: 10px; width: 320px;">
    <TxSearchSelect v-model="value" :options="options" placeholder="Search and pick" />
    <div style="font-size: 12px; color: var(--tx-text-color-secondary, #909399);">
      Value: {{ value }}
    </div>
  </div>
</template>

When remote=true, input changes (debounced) and Enter trigger the search event; fetch externally and write results back to options.

SearchSelect (remote)

Demo will load when visible.
<script setup lang="ts">
import { ref } from 'vue'

const value = ref<string | number>('')
const query = ref('')
const loading = ref(false)

const options = ref<Array<{ value: string, label: string }>>([])

async function onSearch(q: string) {
  query.value = q
  loading.value = true
  await new Promise(resolve => setTimeout(resolve, 220))

  const base = Array.from({ length: 18 }).map((_, i) => `Result ${i + 1}`)
  const list = base
    .filter(s => s.toLowerCase().includes(q.trim().toLowerCase()))
    .slice(0, 12)

  options.value = list.map(s => ({ value: s, label: s }))
  loading.value = false
}
</script>

<template>
  <div style="display: flex; flex-direction: column; gap: 10px; width: 320px;">
    <TxSearchSelect
      v-model="value"
      remote
      :loading="loading"
      :options="options"
      placeholder="Type to remote-search"
      @search="onSearch"
    />

    <div style="font-size: 12px; color: var(--tx-text-color-secondary, #909399);">
      Query: {{ query || '-' }}
    </div>
  </div>
</template>

Notes

  • Local mode filters by options.label and shows all when input is empty.
  • Remote mode requires updating options in the search event; results are not cached.
  • Closing the dropdown keeps input and panel state; reopening does not auto-reset.

API

Props

PropTypeDefaultDescription
modelValuestring | number''Selected option value controlled by v-model.
placeholderstring'Search'Placeholder forwarded to the search input.
disabledbooleanfalseDisables the input, popover, focus open, and remote search emission.
clearablebooleantrueShows the input clear affordance and allows clearing the selected value.
optionsTxSearchSelectOption[][]Option records displayed in the dropdown; disabled options cannot be picked.
loadingbooleanfalseShows a small spinner in the input suffix while results are loading.
remotebooleanfalseDisables local filtering and emits search so the caller can provide external results.
searchDebouncenumber200Debounce delay in milliseconds before emitting remote search after input changes.
dropdownMaxHeightnumber280Maximum options panel height in pixels.
dropdownOffsetnumber6Popover offset from the input reference.
panelVariant'solid' | 'dashed' | 'plain''solid'Popover panel surface variant.
panelBackground'pure' | 'mask' | 'blur' | 'glass' | 'refraction''refraction'Card background style
panelShadow'none' | 'soft' | 'medium''soft'Popover panel shadow strength.
panelRadiusnumber18Popover panel corner radius.
panelPaddingnumber6Popover panel inner padding.

Events

EventParamsDescription
update:modelValue(v: string | number)v-model update emitted after selecting an enabled option or clearing.
change(v: string | number)Emitted with the same value after selection or clear.
search(q: string)Emitted in remote mode after debounce, and immediately on Enter.
select(opt: TxSearchSelectOption)Emitted with the picked enabled option before the dropdown closes.
open-Emitted when the options panel opens.
close-Emitted when the options panel closes; pending remote-search debounce is cleared.

Types

EXAMPLE.TS
export interface TxSearchSelectOption {
  value: string | number
  label: string
  disabled?: boolean
}