0

I have 2 combo box inside grid. The second combo box value will be change base on first combo box.

For example the combo has 3 item : America, Europe, Asia.
If in the first combo box Europe is selected, then in the second combo box, Europe is not appear again.

I don't know which version of extjs I used,

but here's the code :

MY COMBO STORE

var cb_group = Ext.create('Ext.data.Store', {
model: 'cb_group',
autoLoad: false,
proxy: {
    type: 'ajax',
    url: 'srv/master/group/combo',
    reader: {
        type: 'json',
        root: 'rows'
        }
    }
});


MY COMBO INSIDE GRID

var set_approval_dtl = Ext.create('Ext.Window', {
title: title_approval2, width: 850, height: 395, rowdblclick: true, forceFit: true,
closeAction: "hide", store: ms_set_approval_dtl_store,
defaults: {
    sortable: true, resizable: false
},
items: [
    {xtype: "form", items: [
            {layout: 'column', columnWidth: .5, itemId: 'set_approve', defaults: {border: false},
                items: [{xtype: "panel", itemId: "set_approve_panel", height: 330, defaultType: 'textfield', margin: '0 10px 0 10px',
                        defaults: {labelWidth: 120, width: 850, maxLength: 200},
                        items: [
                            {xtype: "grid", itemId: "grid_items", width: 782, height: 280, margin: '0 10px 10px 10px', autoScroll: true,
                                plugins: Ext.create('Ext.grid.plugin.CellEditing', {clicksToEdit: 1, pluginId: 'rowEditing'}),
                                store: ms_set_approval_dtl_store, stripeRows: true, defaultType: "gridcolumn",
                                viewConfig: {forceFit: true},
                                columns: [
                                    {header: grid18j, width: 150, dataIndex: 'nm_act', align: 'center'},
                                    {header: subtitle_approval3, width: 126, dataIndex: 'level1', align: 'center',
                                        editor: {xtype: "combobox", name: "cdgr", itemId: "cdgr1", typeAhead: true, editable: false, triggerAction: "all", forceSelection: true,
                                            emptyText: grid8k, store: cb_group, valueField: "id", displayField: "nm",
                                            listeners: {
                                                expand: function(field, options, val) {
                                                    if (Ext.typeOf(field.getPicker().loadMask) !== "boolean") {
                                                        field.getPicker().loadMask.hide();
                                                    }
                                                },
                                                select: function(value) {
                                                    var obj = this.lastSelection[0].data;
                                                    return obj.nm;
                                                    this.lastSelection[0].hide;
                                                    cb_group.removeAt(0);
                                                }
                                            }},
                                        renderer: function(val) {
                                            var index = cb_group.findExact('id', val);
                                            if (index !== -1) {
                                                var rs = cb_group.getAt(index).data;
                                                return rs.nm;
                                            }
                                        }
                                    },
                                    {header: subtitle_approval4, width: 126, dataIndex: 'level2', align: 'center', itemId: "level2",
                                        editor: {xtype: "combobox", name: "cdgr", itemId: "cdgr2", typeAhead: true, editable: false, triggerAction: "all", forceSelection: true,
                                            emptyText: grid8k, store: cb_group, valueField: "id", displayField: "nm",
                                            listeners: {
                                                expand: function(field, options) {
                                                    if (Ext.typeOf(field.getPicker().loadMask) !== "boolean") {
                                                        field.getPicker().loadMask.hide();
                                                    }
                                                }
                                            }
                                        },
                                        select: function(value) {
                                            var obj = this.lastSelection[0].data;
                                            return obj.nm;
                                        },
                                        renderer: function(val) {
                                            var index = cb_group.findExact('id', val);
                                            if (index !== -1) {
                                                var rs = cb_group.getAt(index).data;
                                                return rs.nm;
                                            }
                                        }
                                    }]
                            }]}
                ]}]}
]});


I've tried this.lastSelection[0].hide; and cb_group.removeAt(0); in the first combo. But it didn't work at all. And I dont know why my select listener is not working.
please share some solution. Thanks

Then Theresia
  • 167
  • 1
  • 11

2 Answers2

0

You can use XTemplates to manage this kind of behavior with one store and two comboboxes.

At first you have to create an XTemplate for your list of items in the combobox:

// displayfield = displayfield configured in your combobox
var template = Ext.create('Ext.XTemplate',
  '<tpl for=".">',
  '  <tpl if="[Ext.getCmp(\'combobox1\').getValue()] != id && [Ext.getCmp(\'combobox2\').getValue()] != id">',
  '    <div class="x-boundlist-item">{label}</div>',
  '  <tpl else>',
  '    <tpl if="id == null || id == \'\'">',
  '      <div class="x-boundlist-item">{label}</div>',
  '    <tpl else>',
  '      <div class="x-boundlist-item" style="font-size:0px; height:0px;"></div>',
  '    </tpl>',
  '  </tpl>',
  '</tpl>'
);

The XTemplate contains some statements to check if the specific value is already selected in one of the comboboxes. If not, then the entry will appear in the dropdown list, otherwise it will be hidden. To make it work, you have to set the template in your combobox and add some listeners to them:

// Combobox 1
{
    xtype: 'combo',
    id: 'combobox1',
    store: 'your_store',
    tpl: template,
    displayField: 'label',
    valueField: 'id',
    listeners: {
    beforeSelect: function (combo, record, index, eOpts)
    {
        // Check if the selected value is already selected in combobox2
        var cbx2value = !!Ext.getCmp('combobox2').getValue() ? Ext.getCmp('combobox2').getValue() : '';

        if (cbx2value != record.get('id') && cbx2value != record.get('id')) {
            return true; // selected entry will be selected successfully
        } else {
            return false; // selected entry will not be selected
        }
    },
    change: function ()
    {
        // Get the picker (list of items) of the other combobox and refresh it's template state
        var cbx2picker = Ext.getCmp('combobox2').getPicker();
        cbx2picker.refresh();
    }
}

// Combobox 2
{
    xtype: 'combo',
    id: 'combobox2',
    store: 'your_store',
    tpl: template,
    displayField: 'label',
    valueField: 'id',
    listeners: {
    beforeSelect: function (combo, record, index, eOpts)
    {
        // Check if the selected value is already selected in combobox2
        var cbx1value = !!Ext.getCmp('combobox1').getValue() ? Ext.getCmp('combobox1').getValue() : '';

        if (cbx1value != record.get('id') && cbx1value != record.get('id')) {
            return true; // selected entry will be selected successfully
        } else {
            return false; // selected entry will not be selected
        }
    },
    change: function ()
    {
        // Get the picker (list of items) of the other combobox and refresh it's template state
        var cbx1picker = Ext.getCmp('combobox1').getPicker();
        cbx1picker.refresh();
    }
}

It's not the ultimate solution, but for one of my projects it worked like a charm. I have simplified the example as good as possible to make the solution clearer.

Tyr
  • 2,810
  • 1
  • 12
  • 21
  • Thanks for your help! But it seems like something didn't work in me. My firebug said Ext.getCmp(...) is undefined. Could you please explain? – Then Theresia Oct 13 '14 at 02:28
  • One of the components you are trying to call doesn't exist with the given id. You can also download the "web developer" addon which shows javascript errors in a quick way. – Tyr Oct 21 '14 at 17:08
-1

You will need two stores, one for each combo box, both filled with the same data.

And then you will do:

combo1.on('select',function(combo, newVal) {
    combo2.getStore().filterBy(function(rec){
        return rec.get("value")!=newVal;
    })
});
Alexander
  • 19,906
  • 19
  • 75
  • 162
  • so I must made 2 store for each combo box? and where do I place the function you mention above? outside var set_approval_dtl? – Then Theresia Oct 09 '14 at 07:13
  • One store for each of the two combo boxes is two stores total. You can take my function and put it into the `listeners : {select:function(combo, newVal)...`, because using listeners object on a component is the same as using `component.on()`. – Alexander Oct 09 '14 at 07:37
  • oh, so each combo box has different store but the data is the same? I can't just call the combo box name. it got error on firebug, says my combo name is not define. – Then Theresia Oct 09 '14 at 07:41
  • No you need 1 store each for 2 comboboxes.You can put the function in the afterRender of your component or you can add it as a listener to the first combobox. – Sreek521 Oct 09 '14 at 07:41
  • Sorry I forgot something. so just put the function that Alexander mention in the first combo box? – Then Theresia Oct 09 '14 at 07:44