Why won't my PrimeVue filterField filter properly on my DataTable Column?

Yesterday I had an interesting experience with some code at work where I was trying to use PrimeVue’s filter option on a DataTable Column. For some reason that I could not understand, the filter was not working on the Column properly.

This is a sample of the kind of code I had for the specific Column. Imagine a data table for displaying tasks where a specific column represents a task’s name, found by it’s uuid.

 <Column field="uuid"  header="Task" filterField="taskUUID" :showFilterMenu="false">
                <template #body="slotProps">
                    <span class="task-title">{{ taskStore.getTaskName(slotProps.data.uuid) }}</span>
                </template>
                <template #filter="{ filterModel, filterCallback }">
                    <Dropdown
                        :options="taskStore.taskNames"
                        optionLabel="name"
                        optionValue="code"
                        v-model="filterModel.value"
                        @change="filterCallback()"
                    />
                </template>
            </Column>

There is a DataTable component that has a value which needs to contain an array of objects. Each field on the object can be put into a Column, with the field prop on the Column being the name of that object’s field.

Then, to enable filtering, you set a filterField on the Column and add a filter slot to a template within the Column, for the filter to display. Into that you pass the filterModel and the filterCallback, which are values that PrimeVue handles but which you need to reference, in my case inside of the Dropdown component, since the Dropdown controls my filter options. The v-model gets set to filterModel.value and filterCallback is invoked on Dropdown value change.

So far so good. In addition I set the optionLabel and optionValue of my Dropdown to be “name” and “code” respectively. This tells the Dropdown which values in the object within the array of options to use when displaying the label and searching for the value of the option.

In my example, the Dropdown of filter options was set to filter on code, which would be the uuid of the task, and the field was set to uuid which would be the task’s uuid, so I thought the two should match; the filterField should know that the two are the same and be able to filter them, bringing up the correct task as being included.

This is what I was expecting to see in my interface:

Instead, when I filtered task by a task I knew was in my data table I got no results:

This was perplexing. I thought that maybe I had to further configure Dropdown to know which value in the options array to use for filtering, but setting optionValue to code should’ve already been doing that.

Fast forward three-ish hours and some code review with the senior dev later, and I thought to myself “huh, nothing is working - I wonder if field and filterField have to be named the same thing". So I changed them to match, and what do you know! it worked!

<Column field="uuid"  header="Task" filterField="uuid" :showFilterMenu="false">
                <template #body="slotProps">
                    <span class="task-title">{{ taskStore.getTaskName(slotProps.data.uuid) }}</span>
                </template>
                <template #filter="{ filterModel, filterCallback }">
                    <Dropdown
                        :options="taskStore.taskNames"
                        optionLabel="name"
                        optionValue="code"
                        v-model="filterModel.value"
                        @change="filterCallback()"
                    />
                </template>
            </Column>

That was all that was needed for the example to successfully filter the data.

Thanks for reading!

Resources:

If you’d like to see more details about DataTable or Dropdown I’ve provided the links to the documentation below.

Please note that in v4 of PrimeVue, Dropdown has been updated to be the Select component, but they work much the same way. (I used Dropdown because our codebase hasn’t updated to use v4 of PrimeVue yet.)