Prevent list display filter from resetting v-list selection

Viewed 17

Version info: Vuetify 2.6.3, Vue 2.6.14, Nuxt 2.15.8

I'm making a custom component that is supposed to be somewhat similar to v-autocomplete, except that it's rendered as bottom sheet. If user enters a display filter into v-text-field, the option list (v-list) is supposed to display only those options that match the filter.

In overall it works fine except one use case: let say the list has 5 items (aa, bb, cc, dd, ee) and user selected bb and cc from the list. Now, v-list-item-group's model selectedItems contains the 2 selected items bb and cc, perfect! However, when user enters b into display filter, the already selected item cc will be auto deleted from selectedItems. I can't tell if selectedItems change is caused by filter or by user selection. Is there a way to maintain the selection in model?

I'm considering a hack - if an item is selected, keep it in filteredChoices even if it does not match the filter. This behaviour is bearable but UX wise not as intuitive as the filter of v-autocomplete.

The simplified structure looks like the below:

<template>
  <v-bottom-sheet scrollable>
    <v-card>
      <v-card-text>
        <v-list>
          <v-list-item-group
              v-model="selectedItems"
              :mandatory="!optional"
              :multiple="multiple"
          >
            <v-list-item
                v-for="item in filteredChoices"
                :key="item.value"
                :value="item"
            >
            </v-list-item>
          </v-list-item-group>
        </v-list>
      </v-card-text>
      <v-text-field
          v-model="filterInput"
          placeholder="filter choices..."
          hide-details
      ></v-text-field>
    </v-card>
  </v-bottom-sheet>
</template>

<script>
  ...
  filteredChoices() {
    if (this.filterInput == null) {
      return this.allItems
    }

    return this.allItems.filter((item) => {
      return item.label
          .toLocaleLowerCase()
          .includes(String(this.filterInput).toLocaleLowerCase())
    })
  },

  ...
</script>
0 Answers
Related