Our blazing fast Grid component built with pure JavaScript


Post by artbil »

Hello !

You can reproduce the bug here https://www.bryntum.com/examples/grid/filterbar/, you just need to add this :

grid.store.addFilter({
  property: "start",
  value: "01/26/2019"
});

grid.store.filter();

addFilter() works correctly but the value "01/26/2019" becomes "01/01/100" after filter(). Is there a workaround or a quick fix for this issue ?

Regards,
artbil


Post by mats »

Looks like a bug yes, we'll look into it and see if there's any workaround available! https://github.com/bryntum/support/issues/3145


Post by Animal »

The Filter object that is created doesn't know that you are comparing to a date.

You are just asking it to compare a field to the string "01/26/2019". Even if it detected that it was a date field, it cannot know that you are thinking about the MM/DD/YYYY format when you type that command.

It has to be this:

grid.store.addFilter({
    property  : "start",
    value     : new Date("01/26/2019")
});

Post by artbil »

Hello,

Thanks for the reply, I tried this (using new Date as you proposed) :

grid.store.addFilter({
  property: "start",
  value: new Date("01/26/2019")
});

grid.store.filter();

But it still change the value of the filter to "01/01/1909" this time. Maybe I forget something ?

Regards,
artbil


Post by Maxim Gorkovsky »

Hello.
If the value of the filter is 01/01/1909 I can assume date input is incorrect. Try to debug and see where is the wrong date comes from. I just tried this filter on a grid celledit demo and it seems to be working just fine.
We would need a runnable test case to assist you.


Post by artbil »

I tried it on grid cell edit demo as well, It works fine when the feature filterBar is not enable but if you enable this feature, you will get the value "01/01/1909".


Post by Maxim Gorkovsky »

Sorry for the confusion. Indeed with FilterBar feature enabled first filter doesn't work despite the input format. That should be covered by the opened issue.


Post by artbil »

Ok thanks, no problem.


Post by Animal »

The piece that is breaking it now is when the FilterBar recreates the Filter from the value that is set into its input field.

You need to override parseFilterValue in the FilterBar class to be like this:

    parseFilterValue(value) {
        if (Array.isArray(value) || ObjectHelper.isDate(value)) { //<-- Dates should be returned unchanged
            return {
                value
            };
        }

    const match = String(value).match(this.filterParseRegExp);

    return {
        operator : match[1] || '*',
        value    : match[2]
    };
}

I cannot remember how to actually apply overrides.


Post by Animal »

Here is what you need to override to fix this.

Put this in the initialization of the app until the next version:

import Override from '../../lib/Core/mixin/Override.js';  <----- You will need to use your correct import path
import FilterBar from '../../lib/Grid/feature/FilterBar.js';  <----- You will need to use your correct import path
import ObjectHelper from '../../lib/Core/helper/ObjectHelper.js';  <----- You will need to use your correct import path

class FilterBarOverride extends Override {
    static get target() {
        return {
            class: FilterBar,
            product: 'grid'
        }
    }

updateColumnFilterFields() {
    const
        me = this,
        {
            columns,
            store
        }  = me.grid;

    let field, filter;

    // During this phase we should not respond to field change events
    me.updatingColumnFilterFields = true;

    for (const column of columns.visibleColumns) {
        field = me.getColumnFilterField(column);
        if (field) {
            filter = store.filters.getBy('property', column.field);
            if (filter) {
                // For filtering functions we keep what user typed into the field, we cannot construct a filter
                // string from them
                if (!filter._filterBy) {
                    field.value = me.buildFilterString(filter);
                }
                else {
                    field.value = filter.value;
                }
            }
            // No filter, clear field
            else {
                field.value = '';
            }
        }
    }
    me.updatingColumnFilterFields = false;
}
  
onColumnFilterFieldChange({ source : field, value }) {
    const
        me         = this,
        { store }  = me.grid;

    // Don't respond if we set the value in response to a filter
    if (!me.updatingColumnFilterFields) {
        // we don't want to hear back store "filter" event
        // so we suspend store tracking
        me.suspendStoreTracking();

        if (value == null || value === '' || Array.isArray(value) && value.length === 0) {
            // remove filter if setting to empty
            store.removeFilter(field.name);
        }
        else {
            store.filter({
                columnOwned : true,
                property    : field.name,
                ...me.parseFilterValue(value)
            });
        }

        me.resumeStoreTracking();
    }
}

buildFilterString(filter) {
    if (ObjectHelper.isDate(filter.value)) {
        return filter.value;
    }
    return (filter.operator === '*' ? '' : filter.operator) + filter.value;
}

  
parseFilterValue(value) {
    if (Array.isArray(value) || ObjectHelper.isDate(value)) {
        return {
            value
        };
    }

    const match = String(value).match(this.filterParseRegExp);

    return {
        operator : match[1] || '*',
        value    : match[2]
    };
}
}
Override.apply(FilterBarOverride);

Post Reply