Photo by Jan Antonin Kolar on Unsplash
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.)