Reputation: 65
I'm using a primereact datatable, and i have a column which is tags, every row of the table has an array of tags.
So i wanted to create a filter, where you have a multiselect form, displaying all the possible tags (the user shouldn't be able to write anything, just use the options the system gives).
I achieved this with a custom filterElement, but when i apply the filter, no matters which tag i select, it will give no results, i think is not filtering well.
I'm using this matchMode
tags: {
operator: FilterOperator.AND,
constraints: [{ value: null, matchMode: FilterMatchMode.IN }]
}
This is my column
<Column
header="Tags"
field="tags"
style={{ minWidth: '16rem' }}
filter
filterElement={(options) => <TagsRowFilterTemplate options={options} />}
sortable
body={(contact) => <TagBodyTemplate contact={contact} tags={tags} />}
/>
And this is my TagsRowFilterTemplate component
export const TagsRowFilterTemplate = ({ options }: TagsFilterProps) => {
const { tags } = useTags()
return (
<MultiSelect
value={options.value ? tagsAsOptionFormat(options.value) : []}
options={tags}
onChange={(e: MultiSelectChangeEvent) => options.filterApplyCallback(e.value, options.index)}
itemTemplate={itemTemplate}
placeholder="Select One or More"
optionLabel="name"
className="p-column-filter"
showClear
style={{ minWidth: '12rem' }}
maxSelectedLabels={3}
filter
/>
)
}
I tried using filterMatchMode, filterFunction, i tried user the matchmode: CONTAINS.
What i expect: To give an example, if i have 2 users:
John Doe with tags: ['foo', 'bar']
Jane Doe with tags: ['foo']
When i filter by foo i want to get jane and joe, but when i filter for bar i want to see only John
Upvotes: 1
Views: 3244
Reputation: 65
I finally solved using custom filtering in a bizarre way.
I guided myself with [this issue] (https://github.com/primefaces/primereact/issues/3325).
And with this codesandbox.
So i registered a new FilterService this way
FilterService.register(ArrayContainsMatchMode, tagRowFilterFunction)
const tagRowFilterFunction = (contactTagIds: string[], filterValue: Tag[]) => {
if (!filterValue || !contactTagIds) return true
if (filterValue.length === 0) return true
else if (filterValue.length !== 0 && contactTagIds.length === 0) return false
const selectedTags = filterValue.map((tag: Tag) => tag.tid)
return selectedTags.every((tid) => contactTagIds.includes(tid))
}
Upvotes: 1