Premium support for our pure JavaScript UI components


Post by TeemuL »

Hi,

Grid's FilterBar-feature is configured during Grid's initialization with a GridConfig. Here is how I do it now:

//other code
filterBar: {
    compactMode: false,
    keyStrokeFilterDelay: 0,
},
//other code

Now, the FilterBar will be visible after the Grid initializes and is rendered on the screen. I would like it to be hidden on startup, so I have to hide it:

grid.features.filterBar.hideFilterBar();

The grid has a custom button to toggle the visibility, so that the user can show it if the feature is needed, otherwise its just bloating the screen if not used. The custom toggle button uses showFilterBar and hideFilterBar -methods depending on the current state.

The problem comes after I call hideFilterBar-method during the rendering stage, as it creates extra read from database because the FilterBar state is changed from visible -> hidden and the filters are considered to be reset, even thought they stay the same.

The situation can be reproduced at https://www.bryntum.com/products/grid/examples/paged/.

  1. Add listening of AjaxStore calls to see the issue on browser console (add the code with comment):

    store    = new AjaxStore({
            modelClass      : GridRowModel,
            readUrl         : '/pagedMockUrl',
            pageParamName   : 'page',
            sortParamName   : 'sort',
            filterParamName : 'filter',
            pageSize        : pageSize,
            autoLoad        : true,
            //count the ajax store data reads
            listeners: {
                beforeRequest: () => {
                   console.count('ajaxstore calls');
                },
            }
        });
    
  2. Initialize the filterbar as in the commented code section:

    const grid = new Grid({
        appendTo : 'container',
    
        store,
    
        // initialize the filterbar
        features : {
            filterBar: {compactMode: false}
        },
    
  3. Hide the filterbar immeditially on startup, as last line on code editor:

    grid.features.filterBar.hideFilterBar();
    

Same code in full:

import { Grid, DataGenerator, AjaxStore, CollectionFilter, BrowserHelper, AjaxHelper, GridRowModel } from '../../build/grid.module.js?463519';
import shared from '../_shared/shared.module.js?463519';

let
    rowCount    = BrowserHelper.searchParam('rowCount') || 250,
    pageSize    = BrowserHelper.searchParam('pageSize') || 25,
    currentPage = 1,
    data        = [];

// This intercepts AjaxHelper.fetch calls and calls AjaxHelper's fetch success handling
// method using a mocked up Fetch Response object with the returned object assigned
// over its default properties. Here we just return responseText with the generated data.
AjaxHelper.mockUrl('/pagedMockUrl', (url, params) => {
    const
        page     = parseInt(params.page, 10),
        pageSize = parseInt(params.pageSize, 10),
        startIdx = (page - 1) * pageSize;

if (data.length !== rowCount) {
    data = DataGenerator.generateData(
        rowCount,
        null,
        1
    );
}

let returnedData = data.slice();

// Filter the data if filter parameter is passed
if (params.filter) {
    returnedData = returnedData.filter(
        CollectionFilter.generateFiltersFunction(
            JSON.parse(params.filter).map(f => {
                f.property = f.field;
                return new CollectionFilter(f);
            })
        )
    );
}

// Sort the data if sort parameter is passed
if (params.sort) {
    returnedData.sort(store.createSorterFn(JSON.parse(params.sort)));
}

return {
    responseText : JSON.stringify({
        success : true,
        total   : returnedData.length,
        data    : returnedData.slice(startIdx, startIdx + pageSize)
    })
};
});

const
    maxCount = 1000,
    minCount = 10,
    store    = new AjaxStore({
        modelClass      : GridRowModel,
        readUrl         : '/pagedMockUrl',
        pageParamName   : 'page',
        sortParamName   : 'sort',
        filterParamName : 'filter',
        pageSize        : pageSize,
        autoLoad        : true,
        //count the ajax store data reads
        listeners: {
            beforeRequest: () => {
               console.count('ajaxstore calls');
            },
        }
    });

const grid = new Grid({
    appendTo : 'container',

store,

// initialize the filterbar
features : {
    filterBar: {compactMode: false}
},

columns : [
    { text : '#', type : 'number', width : 80, field : 'id' },
    { text : 'First name', field : 'firstName', flex : 1 },
    { text : 'Surname', field : 'surName', flex : 1 },
    { text : 'Score', field : 'score', flex : 1, type : 'number' },
    { text : 'Rank', field : 'rank', flex : 1, type : 'number' },
    { text : 'Percent', field : 'percent', width : 150, type : 'percent' }
],

tbar : [
    {
        type        : 'number',
        ref         : 'fieldPageSize',
        placeholder : 'Page size',
        label       : 'Page size',
        tooltip     : 'Enter number of records in each page (10 - 100) and press Apply',
        value       : pageSize,
        width       : '11em',
        min         : minCount,
        max         : maxCount,
        step        : 5
    },
    {
        type        : 'number',
        ref         : 'fieldRowCount',
        placeholder : 'Total records',
        label       : 'Records',
        tooltip     : 'Enter number of records to generate (10 - 1000) and press Apply',
        value       : rowCount,
        width       : '11em',
        min         : minCount,
        max         : maxCount,
        step        : 10
    },
    {
        type    : 'button',
        text    : 'Apply',
        ref     : 'buttonApply',
        icon    : 'b-fa-check',
        tooltip : 'Apply page size and number of records to data loader',
        onClick() {
            rowCount    = grid.widgetMap.fieldRowCount.value;
            pageSize    = store.pageSize = grid.widgetMap.fieldPageSize.value;
            currentPage = store.currentPage = store.currentPage ? Math.min(store.currentPage, Math.floor((rowCount + pageSize - 1) / pageSize)) : 1;
            store.loadPage(currentPage, { rows : rowCount });
        }
    }
],

bbar : {
    type  : 'pagingtoolbar',
    items : {
        // Uncomment this to add an extra button
        // click : {
        //     type    : 'button',
        //     text    : 'Click me',
        //     onClick : () => console.log('Clicked button'),
        //     weight  : 1000 // append to the end of default items
        // }
    }
}
});

grid.features.filterBar.hideFilterBar();

Outcome, there is two calls to fetch the data from backend by the AjaxStore. If you take the last line away, it will only produce 1.

So my question is, can the FilterBar be hidden on startup some other way, or would it be possible to get a feature on FilterBarConfig to make its initial state hidden?

Thanks!


Post by alex.l »

It is, you need to set hidden: true

const grid = new Grid({
    appendTo : 'container',

features : {
    filterBar : {
        compactMode : true,
        hidden : true,
        filter      : { property : 'city', value : 'Paris' }
    },

All the best,
Alex


Post by TeemuL »

Nice, I didn't know that setting existed :) As our project uses Typescript, this is somewhat a problem, as its a property that should not exists in the config. I installed latest version 5.2.3 and this is what the types are:

Grid features (see the filterBar-property):

type GridFeaturesConfigType = {
        cellEdit: string|boolean|Partial<CellEditConfig>
        cellMenu: string|boolean|Partial<CellMenuConfig>
        cellTooltip: string|boolean|Partial<CellTooltipConfig>
        columnAutoWidth: string|boolean|Partial<ColumnAutoWidthConfig>
        columnDragToolbar: string|boolean|Partial<ColumnDragToolbarConfig>
        columnPicker: string|boolean|Partial<ColumnPickerConfig>
        columnRename: string|boolean|Partial<ColumnRenameConfig>
        columnReorder: string|boolean|Partial<ColumnReorderConfig>
        columnResize: string|boolean|Partial<ColumnResizeConfig>
        excelExporter: string|boolean|Partial<ExcelExporterConfig>
        filter: string|boolean|Partial<FilterConfig>
        filterBar: string|boolean|Partial<FilterBarConfig> // <- FilterBarConfig
        group: string|boolean|Partial<GroupConfig>
        groupSummary: string|boolean|Partial<GroupSummaryConfig>
        headerMenu: string|boolean|Partial<HeaderMenuConfig>
        mergeCells: string|boolean|Partial<MergeCellsConfig>
        multipage: string|boolean|Partial<MultiPageExporterConfig>
        multipagevertical: string|boolean|Partial<MultiPageVerticalExporterConfig>
        pdfExport: string|boolean|Partial<PdfExportConfig>
        quickFind: string|boolean|Partial<QuickFindConfig>
        regionResize: string|boolean|Partial<RegionResizeConfig>
        rowCopyPaste: string|boolean|Partial<RowCopyPasteConfig>
        rowExpander: string|boolean|Partial<RowExpanderConfig>
        rowReorder: string|boolean|Partial<RowReorderConfig>
        search: string|boolean|Partial<SearchConfig>
        singlepage: string|boolean|Partial<SinglePageExporterConfig>
        sort: string|boolean|Partial<SortConfig>
        stickyCells: string|boolean|Partial<StickyCellsConfig>
        stripe: string|boolean|Partial<StripeConfig>
        summary: string|boolean|Partial<SummaryConfig>
        tree: string|boolean|Partial<TreeConfig>
        treeGroup: string|boolean|Partial<TreeGroupConfig>
    }

FilterBarConfig is typed like this and it looks like "hidden" is missing, which prevents me from using typescript here:

type FilterBarConfig = {
        bubbleEvents: object
        callOnFunctions: boolean
        client: Widget
        compactMode: boolean
        disabled: boolean
        keyStrokeFilterDelay: number
        listeners: object
        localeClass: typeof Base
        localizable: boolean
        localizableProperties: string[]
        prioritizeColumns: boolean
    }

I can disable type checking for this one as a workaround. Thanks for help!


Post by marcio »

Hey TeemuL,

Thanks for that report, I created a ticket to update the TS type on that config - https://github.com/bryntum/support/issues/5629

Best regards,
Márcio


Post Reply