vuejs3vuetifyjs3

Vuetify v-select with search input changes the selected values


I'm using vuetify 3+ and I'm trying to add a text input so I can search the elements passed in to the v-select component. The problem is that when I do a search, and change the items props input internally the v-select component changes the v-model thus selecting the searched item if any. I don't want that, I need the selection to only happen when I explicitly click on the item checkbox.

<v-select
      :item-title="itemTitle"
      :item-value="itemValue"
      :items="filteredItems"
      :loading="!disabled ? loading : false"
      :menu-props="menuProps"
      :model-value="modelValue"
      :name="name"
      :placeholder="placeholder"
      :prepend-inner-icon="icon"
      :readonly="disabled"
      :required="required"
      :return-object="returnObject"
      :rules="rules"
      attach
      width="220px"
      class="custom-menu-select"
      dense
      density="compact"
      hide-details
      @update:model-value="updateModelValue"
      @update:menu="updateMenu"
    >
      <template v-if="enableSearch" #prepend-item>
        <div class="sticky-header">
          <v-text-field
            v-model="searchQuery"
            :loading="loadingSearch"
            :placeholder="searchLabel"
            append-inner-icon="ibm:Search16"
            class="select-search-input"
            clearable
            density="compact"
            hide-details
            variant="outlined"
            @click:clear="searchQuery = ''"
          ></v-text-field>
        </div>
      </template>
      <template #selection="{ item }">
        <slot :item="item" name="selection">
          <span>{{ item ? item['title'] : placeholder }}</span>
        </slot>
      </template>
      <template #item="{ props, item }">
        <slot :item="item" :props="props" name="item">
          <TooltipPopup
            :disabled="!item.raw.disabled || !item.raw.tooltip"
            :tooltip="item.raw.tooltip"
            placement="right"
          >
            <template #activator>
              <v-list-item
                :disabled="item.raw.disabled"
                density="compact"
                v-bind="props"
              ></v-list-item>
            </template>
          </TooltipPopup>
        </slot>
      </template>
    </v-select>

Above is my select component and here is my filtered computed( I tried with clone and without it and still get the same result)

const filteredItems = computed(() => {
  const clonedItems = [...props.items]
  if (!props.enableSearch) return clonedItems
  if (props.serverSearch) return localItems.value
  if (!searchQuery.value) return clonedItems
  return clonedItems.filter((item) =>
    item[props.itemTitle].toLowerCase().includes(searchQuery.value.toLowerCase())
  )
})

Playground link with replicated problem


Solution

  • Putting @keydown.stop and @keyup.stop on the inner VTextField seems to do the trick:

        <template v-if="items.length > 0" #prepend-item>
          <v-text-field
            v-model="searchQuery"
            ...
            @keydown.stop
            @keyup.stop
          ></v-text-field>
        </template>
    

    See updated playground