bryntum / support

An issues-only repository for the Bryntum project management component suite which includes powerful Grid, Scheduler, Calendar, Kanban Task Board and Gantt chart components all built in pure JS / CSS / TypeScript
https://www.bryntum.com
55 stars 6 forks source link

Correct approach to showing a single "one of" (isIncludedIn) filter in Grid 6.1.2 #10226

Open bmblb opened 1 month ago

bmblb commented 1 month ago

Forum post

I'm trying to just show the "one of" filter, and have users just add and remove chips, and just looking for support as it's not working as I'd hoped.

Here's a modified version of the filtering example:

import  '../_shared/shared.js'; // not required, our example styling etc.
import StringHelper from '../../lib/Core/helper/StringHelper.js';
import Grid from '../../lib/Grid/view/Grid.js';
import '../../lib/Grid/column/DateColumn.js';
import '../../lib/Grid/column/RowNumberColumn.js';
import '../../lib/Grid/feature/QuickFind.js';
import '../../lib/Grid/feature/Stripe.js';
import DataGenerator from '../../lib/Core/helper/util/DataGenerator.js';
import '../../lib/Grid/column/NumberColumn.js';

const grid = new Grid({

appendTo : 'container',

features : {
    filter : { 
        pickerConfig: {
            showAddFilterButton: false,
            canDeleteFilter: (filter) => {
                return false;
            },
            getFieldFilterPickerConfig: (collectionFilterConfig) => {
                return {
                    operatorLocked: true,
                    propertyLocked: true,
                    operators: {
                        string: [
                            {
                                value: "isIncludedIn",
                                text: "Filter by values",
                                argCount: 1
                            }
                        ]
                    },
                    filter: {
                        property: collectionFilterConfig.property,
                        operator: "isIncludedIn",
                        value: collectionFilterConfig.value,
                        disabled: collectionFilterConfig.disabled
                    }
                };
            }
        }
    },
    stripe    : true,
    quickFind : true,
},

tbar : [
    {
        ref      : 'removeAll',
        text     : 'Remove all filters',
        onAction : () => grid.store.clearFilters()
    }
],

stateId: 'test',
columns : [
    { type : 'rownumber' },
    {
        text       : 'Name (custom filter: whole words)',
        field      : 'name',
        flex       : 1,
        // This column has a custom filtering function that matches whole words
        filterable : ({ value, record }) => Boolean(record.name.match(new RegExp(`\\b${StringHelper.escapeRegExp(value)}\\b`, 'i')))
    },
    { text : 'Age', field : 'age', width : 100, type : 'number' },
    { text : 'City', field : 'city' },
    { text : 'When', field : 'start', width : 200, type : 'date' },
    // This column has filtering turned off
    { text : 'Team (no filter)', field : 'team', flex : 1, filterable : false }
],

data : DataGenerator.generateData(100)
});

Changing filters on the City column, it should now just show the value selector, and you can add and remove cities and everything appears to work. However, on removing the last item from the list, the filter doesn't apply.

On my main project, it does fire the filter event, and it seems to correctly have an empty array for the values, but for some reason the results don't change. I'm using state persistence in my main project, and on reloading the state, it does filter correctly.

Does this a bug, or a flaw in my approach to locking to a single filter?

bmblb commented 1 month ago

Checking the code I noticed that:

  1. missingValue = operatorArgCount > 0 && filter?.value == null; this probably does not do what it should. multi select picker returns empty array which is not null. Depending on the variable meaning, this could both mean there is a value (empty array) or there is no value (array is empty).
  2. there is a deliberate check that multiselect field has more than one value: (isMultiSelectValueField && filterValues.length > 0) It is not clear why.
emilschutte commented 1 month ago

I believe this issue is happening because there's no id on the filter. Draft of a fix in the linked PR.