5

I have a Vue component that contains a Vuetify v-data-table component. and it uses the search feature with a <v-text-field>. The problem I'm having is that using the filter function in the headers that are passed as a prop to the data table prevents the search functionality from working.

The data table component uses the body-prepend slot to define select lists to be used for filtering table content.

 <v-data-table
      show-expand
      :headers="headers"
      :items="items"
      :search="search"
      item-key="sow"
      hide-default-footer
      dense
      disable-pagination
    >
      <template v-slot:top>
        <v-toolbar flat color="white">
          <v-toolbar-title>{{ title }}</v-toolbar-title>
          <v-spacer></v-spacer>
          <v-text-field
            v-model="search"
            prepend-icon="search"
            label="Search"
            single-line
            hide-details
            clearable
          ></v-text-field>
        </v-toolbar>
      </template>
      <template v-slot:body.prepend>
        <tr>
          <td :colspan="7"></td>
          <td v-if="showStatusFilter">
            <v-select
              v-model="selectedStatuses"
              :items="statuses"
              :menu-props="{ maxHeight: '400' }"
              label="Select Status"
              multiple
              chips
              deletable-chips
              small-chips
              dense
            ></v-select>
          </td>
          <td v-if="showPracticeFilter">
            <v-select
              v-model="selectedPractices"
              :items="practices"
              label="Select Practice"
              multiple
              chips
              deletable-chips
              small-chips
              dense
            ></v-select>
          </td>
          <td v-if="showSEFilter">
            <v-select
              v-model="selectedSEs"
              :items="ses"
              label="Select SE"
              multiple
              chips
              deletable-chips
              small-chips
              dense
            ></v-select>
          </td>
        </tr>
      </template>
    </v-data-table>

And then the headers are passed in to the component from the parent component

headers: [
  { text: 'SOW', align: 'left', value: 'sow' },
  { text: 'Firm', value: 'firm' },
  { text: 'Category', value: 'category' },
  { text: '% Complete', value: 'percentComplete' },
  { text: 'Estimated Completion', value: 'estimatedCompletionDate' },
  { text: 'Amount', value: 'amount' },
  {
    text: 'Status',
    value: 'status',
    filter: (f) => {
      if (this.getSelectedStatuses.length === 0) return true
        return this.getSelectedStatuses.indexOf(f + '') !== -1
      }
    },
    {
      text: 'Practice',
      value: 'practice'
      filter: (f) => {
        if (this.getSelectedPractices.length === 0) return true
          return this.getSelectedPractices.indexOf(f + '') !== -1
        }
      },
  { text: 'Modified', value: 'modified' },
  { text: 'Actions', value: 'actions' }
],

Vuex is being used to store filtered values so that filters can be used across implementations of the data table component.

Implemented like this, the search field silently dies. However, as soon as I remove the filter functions from the headers array objects, it works just fine. Do I need to implement the filter functions differently? Or should it work like I have it set up? For instance, do I need to dynamically add the filter function to the headers array items within the data table wrapper component instead of passing it in as part of the prop?

1
  • Hey man, did you figure out how to make it works? I am literally with the same problem here. Commented Aug 28, 2021 at 11:05

1 Answer 1

0

They changed the filter functionality on v-data-table several times. Its practically broken in Vuetify 2 with a wont-fix. issue 11600. Here is how i bypassed this in [email protected]

context:

v-data-table takes these issue-related props

  • search: string
  • headers: {filter:(value: unknown, search: string, item: unknown) => boolean}[]

the custom filter fn that you provide in the header prop makes it seem like you can filter per column. However, these functions seem useless given that they only trigger when the search prop changes, providing no benefit than syntactic sugar over the normal table-wide filter function. IMO they should be removed to avoid initial confusion. They are only reactive on the table-wide search string prop.

I made it work per-column by converting all input filter fields into a single json string, then using that string as the search term.

(note that example styling has correct spacing using mx-4)

<v-data-table
  item-key="id"
  :items="items"
  :headers="headers"
  :search="searchterm"
  :custom-filter="() => true"
>
  <template #body.prepend>
    <td><v-text-field class="mx-4 mb-2" v-model="filters.name" label="name" /></td>
    <td><v-text-field class="mx-4 mb-2" v-model="filters.age" label="age" /></td>
  </template>
</v-data-table>
// vue.data
filters = {
  name: null,
  age: null
}

//vue.computed
get searchterm (): string {
  return JSON.stringify(this.filters)
}

//vue.data
headers = [{
  value: 'name',
  filter: (value: unknown, searchterm: string) => {
    const filter = JSON.parse(searchterm)?.name
    if (!filter) return true
    return value === filter
  }
}, {
  value 'age',
  filter: (value: unknown, searchterm: string) => {
    const filter = JSON.parse(searchterm)?.age
    if (!filter) return true
    return value === filter
  }
}]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.