Cascading combos in row cells

Our blazing fast Grid component built with pure JavaScript
Post Reply
User avatar
bensullivan
Posts: 45
Joined: Mon Sep 30, 2019 1:05 pm
Location: Brisbane, Australia

Cascading combos in row cells

Post by bensullivan » Wed Oct 02, 2019 3:34 pm

Hi

Is it possible to have rows in a grid, with each row having three columns, and each column cell containing a combo and when a value is selected in a combo, the other two combos are locally filtered with entries relevant to the value selected in the first combo?

The cascading combos example you have doesn't appear to operate within a grid...

Thanks!

Ben

User avatar
sergey.maltsev
Core Developer
Core Developer
Posts: 187
Joined: Mon Dec 24, 2018 9:15 am

Re: Cascading combos in row cells

Post by sergey.maltsev » Thu Oct 03, 2019 8:54 am

Hi, bensullivan!

You could check this sample code.
Changing filter combo affects on Room dropdown combo.

Code: Select all

import '../_shared/shared.js'; // not required, our example styling etc.
import Grid from '../../lib/Grid/view/Grid.js';
import '../../lib/Grid/column/NumberColumn.js';
import Store from '../../lib/Common/data/Store.js';
import '../../lib/Grid/column/PercentColumn.js';

const roomStore = new Store({
    idField : 'value',
    data    : [
        { value : 1, text : 'One' },
        { value : 2, text : 'Two' },
        { value : 3, text : 'Three' },
        { value : 11, text : 'Eleven' },
        { value : 12, text : 'Twelve' },
        { value : 13, text : 'Thirteen' }
    ]
});

const filterStore = new Store({
    idField : 'min',
    data    : [
        { min : 1, max : 9, text : 'Filter room 1-9' },
        { min : 10, max : 19, text : 'Filter room 10-19' }
    ]
});

const myFields = [
    'person',
    { name : 'room', type : 'number' },
    { name : 'filter', type : 'number' }
];

new Grid({
    appendTo : 'container',
    columns  : [
        {
            field  : 'filter',
            text   : 'Filter',
            editor : {
                type      : 'dropdown',
                store     : filterStore,
                listeners : {
                    change : onFilterComboSelect
                }
            },
            renderer({ record }) {
                const filter = filterStore.getById(record.filter);
                return filter ? filter.text : record.filter;
            },
            width : 200
        },

        {
            field  : 'room',
            text   : 'Room',
            editor : {
                type  : 'dropdown',
                store : roomStore
            },
            renderer({ record }) {
                const room = roomStore.getById(record.room);
                return room ? room.text : record.room;
            },
            width : 200
        },
        {
            field : 'person',
            text  : 'Person',
            width : 100
        }

    ],
    store : new Store({
        fields : myFields,
        data   : [{ room : 1, filter : 1 }]
    })
});

function onFilterComboSelect({ source: combo }) {
    const filter = combo.record;
    roomStore.filter(room => room.value >= filter.min && room.value <= filter.max);
}

User avatar
bensullivan
Posts: 45
Joined: Mon Sep 30, 2019 1:05 pm
Location: Brisbane, Australia

Re: Cascading combos in row cells

Post by bensullivan » Thu Oct 03, 2019 8:55 am

Thankyou!!

User avatar
bensullivan
Posts: 45
Joined: Mon Sep 30, 2019 1:05 pm
Location: Brisbane, Australia

Re: Cascading combos in row cells

Post by bensullivan » Mon Oct 07, 2019 9:35 am

Hi Sergey

I used your code to build the following:

Code: Select all

import {Grid, WidgetHelper, Store} from './build/grid.module.js';

let column = 2;

const myFields = [
    {name: 'person'},
    {name: 'role'},
    {name: 'team'}
];

const personStore = new Store({
    idField: 'value',
    data : [
        { text : 'Select...' },
        { value: 'PER-1', text : 'Bilbo Baggins' },
        { value: 'PER-2', text : 'Samwise Gamjee' },
        { value: 'PER-3', text : 'Peregrin Took' }
    ]  
 });

 const roleStore = new Store({
    idField: 'value',
    data : [
        { text : 'Select...' },
        { value: 'ROL-1', text : 'Hobbit1', person: 'PER-1' },
        { value: 'ROL-2', text : 'Hobbit2', person: 'PER-2' },
        { value: 'ROL-3', text : 'Hobbit3', person: 'PER-3' }
    ]  
 });

const grid = new Grid({
    appendTo: 'target',
    features : {
        cellEdit: true,
        stripe: true
    },
    showDirty: true,
    columns: [
        { 
            field: 'person', 
            text: 'Person', 
            editor : { type : 'dropdown', store : personStore, listeners : { change : onPersonComboChange } },
            renderer({ record }) {
                const person = personStore.getById(record.person);
                return person ? person.text : record.person;
            }, 
            width: 300, 
            locked: true 
        },
        { 
            field: 'role', 
            text: 'Role', 
            editor : { type : 'dropdown', store : roleStore },
            renderer({ record }) {
                const role = roleStore.getById(record.role);
                return role ? role.text : record.role;
            }, 
            width: 300, 
            locked: true 
        },
        { field: 'team', text: 'Team', width: 150, locked: true },
        { text: '2019<br>Nov', type: 'percent', field: 'capacity1', width: 60}
    ],
    store : new Store({
        fields : myFields,
        data   : [
            {person: 'Select...', role: 'Select...', team: 'Select...', capacity1: 0}
        ]
    })
});

function onPersonComboChange({ source: combo }) {
        const filter = combo.record;
        console.log(`Selected person: ${filter.data.value}`);
        roleStore.filter(role => {
            console.log(role.data.person == filter.data.value);
            role.data.person == filter.data.value;
        });
}

WidgetHelper.append([
    {
        type     : 'button',
        ref      : 'removeButton',
        text     : 'Remove Last Month',
        color    : 'b-orange b-raised',
        icon     : 'b-fa b-fa-minus',
        tooltip  : 'Remove Last Month',
        onAction : () => grid.columns.count > 1 && grid.columns.last.remove()
    },
    {
        type     : 'button',
        ref      : 'addButton',
        text     : 'Add Month',
        color    : 'b-green b-raised',
        icon     : 'b-fa b-fa-plus',
        tooltip  : 'Add new month',
        onAction : () => {
            const fieldName = `capacity${column++}`;
            myFields.push({ name : fieldName, type : 'percent', text: 'Dec', width: 60 });

            const store = new Store({
                fields : myFields,
                data   : grid.store.records.map(r => r.data)
            });

            grid.store = store;
            grid.refreshRows();
            grid.columns.add({ text : 'Dec', type : 'percent', field : fieldName, width : 100 });
            // grid.store.add({ id : grid.store.count + 1, [fieldName] : column });
            
            
            // grid.columns.add({ text: 'Dec', type: 'percent', field: 'capacity2', width: 60});
        }
    }  
], { insertFirst : document.getElementById('gridButtons') || document.body });
For some reason, the listener is firing for both person and role combos and I don' understand why. Also, the roleStore.filter call in the listener does not appear to be filtering the role dropdown contents after the listener finishes execution. Can you see what I'm doing wrong?

Thanks!

Ben

User avatar
bensullivan
Posts: 45
Joined: Mon Sep 30, 2019 1:05 pm
Location: Brisbane, Australia

Re: Cascading combos in row cells

Post by bensullivan » Mon Oct 07, 2019 11:23 am

I seemed to get it working with this code:

Code: Select all

import {Grid, Store} from './build/grid.module.js';

const personStore = new Store({
    idField : 'personId',
    data    : [
        { personId : 'PER-1', text : 'Bilbo' },
        { personId : 'PER-2', text : 'Samwise' },
        { personId : 'PER-3', text : 'Peregrine' }
    ]
});

const roleStore = new Store({
    idField : 'roleId',
    data    : [
        { roleId : 'ROL-1', text : 'Farmer', personId: 'PER-1'},
        { roleId : 'ROL-2', text : 'Cook', personId: 'PER-3' }
    ]
});

const myFields = [
    'team',
    { name : 'person' },
    { name : 'role' }
];

new Grid({
    appendTo : 'target',
    columns  : [
        {
            field  : 'role',
            text   : 'Role',
            editor : {
                type      : 'dropdown',
                store     : roleStore,
                listeners : {
                    change : onRoleComboChange
                }
            },
            renderer({ record }) {
                const role = roleStore.getById(record.role);
                return role ? role.text : record.role;
            },
            width : 200
        },
        {
            field  : 'person',
            text   : 'Person',
            editor : {
                type  : 'dropdown',
                store : personStore
            },
            renderer({ record }) {
                const person = personStore.getById(record.person);
                return person ? person.text : record.person;
            },
            width : 200
        },
        {
            field : 'team',
            text  : 'Team',
            width : 100
        }

    ],
    store : new Store({
        fields : myFields,
        data   : [{ role : 'Cook' }]
    })
});

// function onFilterComboSelect({ source: combo }) {
function onRoleComboChange({ source: roleCombo }) {
    const filterRole = roleCombo.record;
    personStore.filter(person => person.personId == filterRole.personId);
}
Is it possible to clear a column dropdown editor from a listener function?
Is it possible to clear a dropdown from in the combo itself like on the cascading combo example?
Can a column dropdown editor be activated without having to double click on the cell?

Thanks

Ben

User avatar
sergey.maltsev
Core Developer
Core Developer
Posts: 187
Joined: Mon Dec 24, 2018 9:15 am

Re: Cascading combos in row cells

Post by sergey.maltsev » Mon Oct 07, 2019 12:00 pm

Hi!

You can update personStore whenever you want and this will update dropdown list when editor is shown.

You can start editing with grid.startEditing() method.
https://www.bryntum.com/docs/grid/#Grid/view/Grid#function-startEditing

To show dropdown just call inputField.showPicker()
https://www.bryntum.com/docs/grid/#Common/widget/PickerField#function-showPicker

This code clears personStore and shows empty dropdown.

Code: Select all

if (grid.startEditing({
    record : grid.store.first,
    field  : 'person' })) {
    personStore.clear();
    grid.features.cellEdit.editorContext.editor.inputField.showPicker();
}

User avatar
bensullivan
Posts: 45
Joined: Mon Sep 30, 2019 1:05 pm
Location: Brisbane, Australia

Re: Cascading combos in row cells

Post by bensullivan » Tue Oct 08, 2019 4:12 am

Is it possible to configure a grid such that the editing of a cell is initiated by a single click instead of a double click?

I'm guessing this might interfere with the fact that a row in a grid is selected by a single click?

Thanks

Ben

User avatar
sergey.maltsev
Core Developer
Core Developer
Posts: 187
Joined: Mon Dec 24, 2018 9:15 am

Re: Cascading combos in row cells

Post by sergey.maltsev » Tue Oct 08, 2019 5:25 am

Hi!

Please next time create new post for each separate question.

You can use cellClick event to process single click with your own way.
https://www.bryntum.com/docs/grid/#Grid/view/mixin/GridElementEvents#event-cellClick

Code: Select all

grid.on('cellClick', ({ source, record, cellSelector, cellElement, target, event }) => console.log('click'))
More info on using events can be found here
https://www.bryntum.com/docs/grid/#Common/mixin/Events

Also on touch devices if you tap on selected cell again this will open editor.

User avatar
bensullivan
Posts: 45
Joined: Mon Sep 30, 2019 1:05 pm
Location: Brisbane, Australia

Re: Cascading combos in row cells

Post by bensullivan » Tue Oct 08, 2019 5:38 am

Hi Sergey

Apologies for not creating a new post and thanks for the reply.

Cheers

Ben

User avatar
sergey.maltsev
Core Developer
Core Developer
Posts: 187
Joined: Mon Dec 24, 2018 9:15 am

Re: Cascading combos in row cells

Post by sergey.maltsev » Wed Oct 09, 2019 7:18 am

Hi!

You are welcome!

Post Reply