Our pure JavaScript Scheduler component


Post by NationalGroup »

Hello I am trying to achieve a functionality of smart filter.I have created a video to explain the exact functionality . Kindly let me know how to achieve this.
Please go through the bottom link for the video description.
https://drive.google.com/file/d/1LkqLwogDQFuc7v7a53VZ6TieJz5c5ip5/view?usp=sharing
Regards


Post by pmiklashevich »

You can subscribe to selectionChange and apply filter to the Grid store.

scheduler.on('selectionchange', () => grid.store.filterBy(() => {.....}));

If you need a UI element to adjust the filter condition, you can use Slider for example and pass its value to the filter.

Pavlo Miklashevych
Sr. Frontend Developer


Post by NationalGroup »

can you kindly provide a working example of that and actually I want to filter on a particular click as I mentiioned in the above video?


Post by pmiklashevich »

Please modify examples/dragfromgrid/app.js file and run the demo locally.
Docs:
https://www.bryntum.com/docs/scheduler/#Core/data/mixin/StoreFilter#function-filter
https://www.bryntum.com/docs/scheduler/#Scheduler/view/Scheduler#config-selectionMode
https://www.bryntum.com/docs/scheduler/#Scheduler/view/Scheduler#event-selectionChange

import '../_shared/shared.js'; // not required, our example styling etc.
import Splitter from '../../lib/Core/widget/Splitter.js';

import UnplannedGrid from './lib/UnplannedGrid.js';
import Schedule from './lib/Schedule.js';
import Drag from './lib/Drag.js';
import Task from './lib/Task.js';
import TaskStore from './lib/TaskStore.js';

let scheduler = new Schedule({
    selectionMode : {
        row         : true,
        multiSelect : true
    },
    ref         : 'schedule',
    insertFirst : 'main',
    startDate   : new Date(2025, 11, 1, 8),
    endDate     : new Date(2025, 11, 1, 18),
    flex        : 1,
    crudManager : {
        autoLoad   : true,
        eventStore : {
            storeClass : TaskStore
        },
        transport : {
            load : {
                url : 'data/data.json'
            }
        }
    },

tbar : [
    '->',
    {
        type      : 'slider',
        ref       : 'filterRange',
        text      : 'Filter range: MIDDLE',
        min       : 0,
        max       : 2,
        value     : 1,
        showValue : false,
        width     : 200,
        listeners : {
            change({ value }) {
                this.text = `Filter range: ${value === 0 ? 'MIN' : (value === 2 ? 'MAX' : 'MIDDLE')}`;
            }
        }
    },
    {
        type    : 'button',
        icon    : 'b-fa-times',
        tooltip : 'Clear resource selection',
        onClick() {
            scheduler.deselectAll();
        }
    }
]
});

new Splitter({
    appendTo : 'main'
});

const unplannedGrid = new UnplannedGrid({
    ref      : 'unplanned',
    appendTo : 'main',
    // Schedulers stores are contained by a project, pass it to the grid to allow it to access them
    project  : scheduler.project,
    flex     : '0 1 300px',
    store    : {
        modelClass : Task,
        readUrl    : 'data/unplanned.json',
        autoLoad   : true
    },
    tbar : [
        'Grid view'
    ]

});

const drag = new Drag({
    grid         : unplannedGrid,
    schedule     : scheduler,
    constrain    : false,
    outerElement : unplannedGrid.element
});

scheduler.on('selectionchange', ({ selection : resources }) => {
    if (resources.length) {
        // Extract data you need from resources
        console.log(resources.map(record => record.name));

    const filterRange = scheduler.widgetMap.filterRange.value;
    console.log(filterRange);

    unplannedGrid.store.filter({
        id       : 'my-filter',
        filterBy : record => record.duration > 3
    });
}
else {
    unplannedGrid.store.removeFilter('my-filter');
    console.log('Filter removed!');
}
});
Запись активности на экране 2021-04-09 в 16.34.38.gif
Запись активности на экране 2021-04-09 в 16.34.38.gif (3.26 MiB) Viewed 552 times

Pavlo Miklashevych
Sr. Frontend Developer


Post by NationalGroup »

Hello thanks for the above demo but it is not suitable for my requirement. In my case I need to hit a get API and interact to backend to fetch the data of right grid(of jobs) .The exact requirement is when user click on any name on left grid then I hit an API of get with two parameters(1:name, 2: distance selected from above dropdown) and when I get the response I refresh the right grid of jobs only.Kindly let me know how to do it.I do not want to use inbuilt filter of grid instead I want the backend to provide me the filtered data via API call.


Post by pmiklashevich »

Remote filtering is supported. Please read:
https://www.bryntum.com/docs/scheduler/#Core/data/AjaxStore#remote-filtering
https://www.bryntum.com/docs/scheduler/#Core/data/AjaxStore#config-filterParamName
https://www.bryntum.com/docs/scheduler/#Core/data/AjaxStore#function-encodeFilterParams

Here is a small example for reference (Scheduler/examples/dragfromgrid/app.js):

import '../_shared/shared.js'; // not required, our example styling etc.
import Splitter from '../../lib/Core/widget/Splitter.js';

import UnplannedGrid from './lib/UnplannedGrid.js';
import Schedule from './lib/Schedule.js';
import Drag from './lib/Drag.js';
import Task from './lib/Task.js';
import TaskStore from './lib/TaskStore.js';

const scheduler = new Schedule({
    selectionMode : {
        row         : true,
        multiSelect : true
    },
    ref         : 'schedule',
    insertFirst : 'main',
    startDate   : new Date(2025, 11, 1, 8),
    endDate     : new Date(2025, 11, 1, 18),
    flex        : 1,
    crudManager : {
        autoLoad   : true,
        eventStore : {
            storeClass : TaskStore
        },
        transport : {
            load : {
                url : 'data/data.json'
            }
        }
    },

tbar : [
    '->',
    {
        type      : 'slider',
        ref       : 'filterRange',
        text      : 'Filter range: MIDDLE',
        min       : 0,
        max       : 2,
        value     : 1,
        showValue : false,
        width     : 200,
        listeners : {
            change({ value }) {
                this.text = `Filter range: ${value === 0 ? 'MIN' : (value === 2 ? 'MAX' : 'MIDDLE')}`;

                // Update filter only when there is at least one selected resource
                if (scheduler.selectedRecords.length) {
                    unplannedGrid.store.filter([
                        {
                            id       : 'range-filter',
                            property : 'range',
                            operator : '=',
                            value    : value
                        }
                    ]);

                    // Changing the filters makes the store to reload the data. No need to reload the store manually.
                }
            }
        }
    },
    {
        type    : 'button',
        icon    : 'b-fa-times',
        tooltip : 'Clear resource selection',
        onClick() {
            scheduler.deselectAll();
        }
    }
]
});

new Splitter({
    appendTo : 'main'
});

const unplannedGrid = new UnplannedGrid({
    ref      : 'unplanned',
    appendTo : 'main',
    // Schedulers stores are contained by a project, pass it to the grid to allow it to access them
    project  : scheduler.project,
    flex     : '0 1 300px',
    store    : {
        modelClass      : Task,
        readUrl         : 'data/unplanned.json',
        autoLoad        : true,
        filterParamName : 'filterKey'
    },
    tbar : [
        'Grid view'
    ]
});

const drag = new Drag({
    grid         : unplannedGrid,
    schedule     : scheduler,
    constrain    : false,
    outerElement : unplannedGrid.element
});

scheduler.on('selectionchange', ({ selection : resources }) => {
    if (resources.length) {
        unplannedGrid.store.filter([
            {
                id       : 'selected-resources',
                property : 'resources',
                operator : '=',
                value    : resources.map(record => record.id).join(',')
            },
            {
                id       : 'range-filter',
                property : 'range',
                operator : '=',
                value    : scheduler.widgetMap.filterRange.value
            }
        ]);
    }
    else {
        unplannedGrid.store.clearFilters();
    }

// Changing the filters makes the store to reload the data. No need to reload the store manually.
});
Запись активности на экране 2021-04-12 в 10.27.46.gif
Запись активности на экране 2021-04-12 в 10.27.46.gif (14.43 MiB) Viewed 525 times

Pavlo Miklashevych
Sr. Frontend Developer


Post Reply