Shuls
Shuls

Reputation: 65

Filtering with multiple values over an array column in Primereact Datatable

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

Answers (1)

Shuls
Shuls

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

Related Questions