PDA

View Full Version : ExtJS--create/clone new stores for treecombo when new grid row is added



JackJohnsonX
18 Feb 2015, 11:03 AM
I have an editable grid that uses 4 instances of the custom "treecombo" extjs component. Theres 4 columns that use treecombo as an editor. I differentiate these 4 combos by itemId. The 4 treecombos all use separate stores.

The problem is, I have selective filtering implemented on the comboboxes. Meaning, when an item is selected, I filter/load the remaining combos. Think of a Country/State/City/Zip type scenario. When country is selected, the states are loaded accordingly, when state is selected, cities are loaded accordingly etc. So when I add a new row to the grid and make a selection in row 2 for example, ALL the combos in ALL the rows get filtered, not just in row 2. The selections in row 1 wont get cleared/reset which is fine, but if i was to go back and change a selection in row 1, the results I will be seeing in the drop down list will be the filtered results based on row 2 selections, not row 1 selections.

So my question is, is there a way to make the combos stores in each row independent of combo stores in other rows? Or a way to dynamically create/clone new stores for the 4 combos whenever a new row is added??
Thank you in advance..
//grid editors




this.columns = [
{
header:"Country",
dataIndex:"country",
flex:1,
editor:Ext.create("MyApp.form.field.TreeCombo",{ selectChildren: true, itemId:"country", store:"Countries", treeWidth:240, displayField:"text", valueField:"text"})
},
{
header:"State",
dataIndex:"state",
flex:1,
editor:Ext.create("MyApp.form.field.TreeCombo",{ itemId:"state", store:"States", treeWidth:240, displayField:"text", valueField:"text"})
},
{
header:"Cities",
dataIndex:"cities",
flex:1,
editor:Ext.create("MyApp.form.field.TreeCombo",{ itemId:"cities", treeWidth:240, store:"Cities", displayField:"text", valueField:"text"})
},
{
header:"Zip",
dataIndex:"zip",
flex:1,
editor:Ext.create("MyApp.form.field.TreeCombo",{ itemId:"zip", treeWidth:240, store:"Zip", displayField:"text", valueField:"text"})
}
];

//treecombo source--note, it actually extends field.Picker, not field.ComboBox

Ext.define('MyApp.form.field.TreeCombo', {
extend: 'Ext.form.field.Picker',
alias: 'widget.treecombo',
tree: false,
constructor: function(config)
{
this.addEvents(
{
"itemclick" : true
});


this.listeners = config.listeners;
this.callParent(arguments);
},
records: [],
recursiveRecords: [],
ids: [],
selectChildren: true,
canSelectFolders: true,
multiselect: false,
displayField: 'text',
valueField: 'text',
treeWidth: 300,
matchFieldWidth: true,
treeHeight: 400,
masN: 0,
recursivePush: function(node, setIds)
{
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(elt /*, from*/)
{
var len = this.length >>> 0;

var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;

for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
var me = this;


me.addRecRecord(node);
if(setIds) me.addIds(node);

node.eachChild(function(nodesingle)
{
if(nodesingle.hasChildNodes() == true)
{
me.recursivePush(nodesingle, setIds);
}
else
{
me.addRecRecord(nodesingle);
if(setIds) me.addIds(nodesingle);
}
});
},
recursiveUnPush: function(node)
{
var me = this;
me.removeIds(node);

node.eachChild(function(nodesingle)
{
if(nodesingle.hasChildNodes() == true)
{
me.recursiveUnPush(nodesingle);
}
else me.removeIds(nodesingle);
});
},
addRecRecord: function(record)
{
var me = this;


for(var i=0,j=me.recursiveRecords.length;i<j;i++)
{
var item = me.recursiveRecords[i];
if(item)
{
if(item.getId() == record.getId()) return;
}
}
me.recursiveRecords.push(record);
},
afterLoadSetValue: false,
setValue: function(valueInit)
{
if(typeof valueInit == 'undefined') return;

var me = this,
tree = this.tree,
values = (valueInit == '') ? [] : valueInit.split(','),
valueFin = [];

inputEl = me.inputEl;


if(tree.store.isLoading())
{
me.afterLoadSetValue = valueInit;
}


if(inputEl && me.emptyText && !Ext.isEmpty(values))
{
inputEl.removeCls(me.emptyCls);
}


if(tree == false) return false;

var node = tree.getRootNode();
if(node == null) return false;

me.recursiveRecords = [];
me.recursivePush(node, false);

me.records = [];
Ext.each(me.recursiveRecords, function(record)
{
var id = record.get(me.valueField);

var index = values.indexOf(""+id);

if(me.multiselect == true) record.set('checked', false);

if(index != -1)
{
valueFin.push(record.get(me.displayField));
if(me.multiselect == true) record.set('checked', true);
me.addRecord(record);
}
});


me.value = valueInit;
me.setRawValue(valueFin.join(', '));

me.checkChange();
me.applyEmptyText();
return me;
},
getValue: function()
{
return this.value;
},
getSubmitValue: function()
{
return this.value;
},
checkParentNodes: function(node)
{
if(node == null) return;

var me = this,
checkedAll = true;


node.eachChild(function(nodesingle)
{
var id = nodesingle.getId(),
index = me.ids.indexOf(''+id);

if(index == -1) checkedAll = false;
});

if(checkedAll == true)
{
me.addIds(node);
me.checkParentNodes(node.parentNode);
}
else
{
me.removeIds(node);
me.checkParentNodes(node.parentNode);
}
},
initComponent: function()
{
var me = this;

me.tree = Ext.create('Ext.tree.Panel',
{
alias: 'widget.assetstree',
hidden: true,
minHeight: 300,
rootVisible: (typeof me.rootVisible != 'undefined') ? me.rootVisible : true,
floating: true,
useArrows: true,
width: me.treeWidth,
autoScroll: true,
height: me.treeHeight,
store: me.store,
listeners:
{
load: function(store, records)
{
if(me.afterLoadSetValue != false)
{
me.setValue(me.afterLoadSetValue);
}
},
itemclick: function(view, record, item, index, e, eOpts)
{
me.itemTreeClick(view, record, item, index, e, eOpts, me)
}
}
});

if(me.tree.getRootNode().get('checked') != null) me.multiselect = true;

this.createPicker = function()
{
var me = this;
return me.tree;
};

this.callParent(arguments);
},
addIds: function(record)
{
var me = this;

if(me.ids.indexOf(''+record.getId()) == -1) me.ids.push(''+record.get(me.valueField));
},
removeIds: function(record)
{
var me = this,
index = me.ids.indexOf(''+record.getId());

if(index != -1)
{
me.ids.splice(index, 1);
}
},
addRecord: function(record)
{
var me = this;


for(var i=0,j=me.records.length;i<j;i++)
{
var item = me.records[i];
if(item)
{
if(item.getId() == record.getId()) return;
}
}
me.records.push(record);
},
removeRecord: function(record)
{
var me = this;


for(var i=0,j=me.records.length;i<j;i++)
{
var item = me.records[i];
if(item && item.getId() == record.getId()) delete(me.records[i]);
}
},
itemTreeClick: function(view, record, item, index, e, eOpts, treeCombo)
{

var me = treeCombo,
checked = !record.get('checked');//it is still not checked if will be checked in this event

if(me.multiselect == true) record.set('checked', checked);//check record

var node = me.tree.getRootNode().findChild(me.valueField, record.get(me.valueField), true);
me.setValue(record.data.text);
if(node == null)
{
if(me.tree.getRootNode().get(me.valueField) == record.get(me.valueField)) node = me.tree.getRootNode();
else return false;
}

if(me.multiselect == false) me.ids = [];

//if it can't select folders and it is a folder check existing values and return false
if(me.canSelectFolders == false && record.get('leaf') == false)
{
me.setRecordsValue(view, record, item, index, e, eOpts, treeCombo);
return false;
}

//if record is leaf
if(record.get('leaf') == true)
{
if(checked == true)
{
me.addIds(record);
}
else
{
me.removeIds(record);
}
}
else //it's a directory
{
me.recursiveRecords = [];
if(checked == true)
{
if(me.multiselect == false)
{
if(me.canSelectFolders == true) me.addIds(record);
}
else
{
if(me.canSelectFolders == true)
{
me.recursivePush(node, true);
}
}
}
else
{
if(me.multiselect == false)
{
if(me.canSelectFolders == true) me.recursiveUnPush(node);
else me.removeIds(record);
}
else me.recursiveUnPush(node);
}
}

//this will check every parent node that has his all children selected
if(me.canSelectFolders == true && me.multiselect == true) me.checkParentNodes(node.parentNode);

me.setRecordsValue(view, record, item, index, e, eOpts, treeCombo);
},
fixIds: function()
{
var me = this;

for(var i=0,j=me.ids.length;i<j;i++)
{
if(me.ids[i] == 'NaN') me.ids.splice(i, 1);
}
},
setRecordsValue: function(view, record, item, index, e, eOpts, treeCombo)
{
var me = treeCombo;

me.fixIds();

me.setValue(me.ids.join(','));


me.fireEvent('itemclick', me, record, item, index, e, eOpts, me.records, me.ids);


if(me.multiselect == false) me.onTriggerClick();
}
});

any help helps, thx
forgot to mention--there can be X number of rows which complicates this even further

joel.watson
6 Mar 2015, 7:51 AM
Hi Jack--

Since you're implementing a custom component, I would suggest creating a test case that demonstrates the problem: https://fiddle.sencha.com

Thanks
Joel