I have 2 MultiSelects
in an ItemSelector
, itself in a FormPanel
. Each MultiSelect
is posed of 2 Stores
: left side, and right side (with arrows to move items between the 2).
When I load the panel, I feed a reference, in order to highlight the items moved from one side to the other (e.g. set style as red for moved items) because today there is no way to differentiate them.
I managed to catch event afterAdd
on the Stores
and apply my style through DOM access. That works during trace, but later on remaining ExtJS standard calls are performed, overriding the style I just applied...
I feel what I'm doing is not the good way, but I'm new to ExtJS so I'm a bit lost here... Thanks for your help !
EDIT : here is a sample of my code, I forgot to tell that I worked on ExtJS 3.2 (hum...). pool_cnx_to_rule
is my FormPanel
:
pool_cnx_to_rule.afterMethod('add', function ()
{
//var pools_available_ = Ext.getCmp('pools_available').getValue();
var pools_selected_ = Ext.getCmp('pools_selected').getValue();
var i, j;
for (i = 0; i < pool_cnx_to_rule.data.length; ++i)
{
var pool_descr_ = pool_cnx_to_rule.data.items[i].data.pool_descr;
var changed = true;
for (j = 0; j < pool_cnx_to_rule_ref.length; ++j)
{
if (pool_cnx_to_rule_ref[j] == pool_descr_)
{
changed = false;
break;
}
}
if (changed)
{
var pools_selected_ = Ext.getCmp('pools_selected');
var nodes_ = pools_selected_.view.getNodes();
var node_ = nodes_[j];
var record_ = pools_selected_.view.getRecord(node_);
record_.set('color', 'red');
// Instead of assigning pools_selected_.view, create var
var view_ = new Ext.ListView({
multiSelect: true,
store: pools_selected_.store,
columns: [{
dataIndex: pools_selected_.displayField,
header: 'Value',
width: 1,
tpl: new Ext.XTemplate(
'<tpl if="red==true">',
'<div class="red">{' + pools_selected_.displayField + '}</div>',
'<tpl else>',
'<div>{' + this.displayField + '}</div>',
'</tpl>'
),
}],
hideHeaders: true
});
pools_selected_.fs.items.clear();
pools_selected_.fs.add(view_);
pools_selected_.fs.doLayout();
}
}
});
I have 2 MultiSelects
in an ItemSelector
, itself in a FormPanel
. Each MultiSelect
is posed of 2 Stores
: left side, and right side (with arrows to move items between the 2).
When I load the panel, I feed a reference, in order to highlight the items moved from one side to the other (e.g. set style as red for moved items) because today there is no way to differentiate them.
I managed to catch event afterAdd
on the Stores
and apply my style through DOM access. That works during trace, but later on remaining ExtJS standard calls are performed, overriding the style I just applied...
I feel what I'm doing is not the good way, but I'm new to ExtJS so I'm a bit lost here... Thanks for your help !
EDIT : here is a sample of my code, I forgot to tell that I worked on ExtJS 3.2 (hum...). pool_cnx_to_rule
is my FormPanel
:
pool_cnx_to_rule.afterMethod('add', function ()
{
//var pools_available_ = Ext.getCmp('pools_available').getValue();
var pools_selected_ = Ext.getCmp('pools_selected').getValue();
var i, j;
for (i = 0; i < pool_cnx_to_rule.data.length; ++i)
{
var pool_descr_ = pool_cnx_to_rule.data.items[i].data.pool_descr;
var changed = true;
for (j = 0; j < pool_cnx_to_rule_ref.length; ++j)
{
if (pool_cnx_to_rule_ref[j] == pool_descr_)
{
changed = false;
break;
}
}
if (changed)
{
var pools_selected_ = Ext.getCmp('pools_selected');
var nodes_ = pools_selected_.view.getNodes();
var node_ = nodes_[j];
var record_ = pools_selected_.view.getRecord(node_);
record_.set('color', 'red');
// Instead of assigning pools_selected_.view, create var
var view_ = new Ext.ListView({
multiSelect: true,
store: pools_selected_.store,
columns: [{
dataIndex: pools_selected_.displayField,
header: 'Value',
width: 1,
tpl: new Ext.XTemplate(
'<tpl if="red==true">',
'<div class="red">{' + pools_selected_.displayField + '}</div>',
'<tpl else>',
'<div>{' + this.displayField + '}</div>',
'</tpl>'
),
}],
hideHeaders: true
});
pools_selected_.fs.items.clear();
pools_selected_.fs.add(view_);
pools_selected_.fs.doLayout();
}
}
});
Share
Improve this question
edited May 20, 2013 at 15:22
Emmanuel
asked May 14, 2013 at 11:04
EmmanuelEmmanuel
14.2k12 gold badges53 silver badges73 bronze badges
2
- lol :) Ext 3.2, small detail you forgot to mention here :) – VDP Commented May 17, 2013 at 7:48
- Yes, sorry, I'm currently whipping myself for that :) – Emmanuel Commented May 17, 2013 at 8:00
2 Answers
Reset to default 4 +150For Ext 4.2
Here is a fiddle which colors the records you choose. (to use it, select some items and press 'red'..) It does not take care of adding and catching events only the coloring of selected items, as I understand this is the problematic part for you.
Basically I added a listConfig to the multiSelection, which transfers it to it's boundList:
listConfig: {
itemTpl: '<div class="my-boundlist-item {color}">{numberName}</div>',
}
The template is getting it's values from the multiselect store, so we can just set the "color" field for the records we want:
myRecord.set('color', 'red');
By doing this the item which we set will now have the class 'red'. Last thing was to add css for the class:
.red {
background-color: rgba(255,0,0,0.2);
}
Note that I made it quite transparent, so the selection and hovering color will still be noticeable.
For Ext 3.2
Here is the fiddle. As @VDP mentioned, Ext 3.2 uses ListView for the multiselect, which can get a tpl config (templatecolumn is actually not available for listview, just for grid)
However MultiSelect doesn't expose this config, so we have to override the onRender of multiselect, here is the interesting part:
Ext.ux.form.ConfigurableMultiSelect = Ext.extend(Ext.ux.form.MultiSelect, {
listItemTpl: null,
onRender: function(ct, position){
...
var listItemTpl = this.listItemTpl || '<div>{'+this.displayField+'}</div>';
this.view = new Ext.ListView({
multiSelect: true,
store: this.store,
columns: [{
dataIndex: this.displayField,
header: 'Value',
width: 1,
tpl: listItemTpl
}],
hideHeaders: true
});
...
Now we can use the extended class to pass a listItemTpl config to the view:
items: [{
xtype: 'confmultiselect', //the new xtype we registered
fieldLabel: 'Multiselect',
name: 'multiselect',
id: 'multiselect-field',
allowBlank: false,
displayField: 'text',
store: store,
listItemTpl: '<div class="inner-boundlist-item {color}">{text}</div>',
}],
The rest is pretty much the same as in Ext 4.2
It's not really clear for me when you want it to be marked.
What I would do is attach a listener on the store of the fromField
and/or the toField
Lets say we want all items, removed from the toField, marked:
// somewhere after setupItems (that's where the lists got created)
itemSelector.toField.store.on('remove', itemSelector.onRemoveItem);
onRemoveItem = function(record){
record.set('removed', true);
}
// on the 'Ext.view.BoundList' of the fromField I would change my itemTpl and
// check if removed is true in the template. If so, add a class
// refresh the list
It's not a ready-made solution but maybe this gets you on track...
UPDATE:
@Amit Aviv just wrote in detail what I meant with 'change' the itemTpl to add a class
what I had in mind was something like this:
listConfig: {
itemTpl: new Ext.XTemplate(
'<tpl if="removed==true">',
'<div class="my-boundlist-item removed">{value}</div>',
'<tpl else>',
'<div class="my-boundlist-item">{value}</div>',
'</tpl>'
)
}
The rest is the same. Amit's solution is just as good ;)
In Ext 3 and itemselector contains 2 Ext.ux.form.MultiSelect
. A MultiSelect has a Ext.ListView where in Ext 4 it uses a BoundList. This ListView is very similar to a grid.
It has no itemTpl, but it has columns. You can override onRender of the MultiSelect so you can insert your own column in the ListView. This is the part to be modified:
this.view = new Ext.ListView({
multiSelect: true,
store: this.store,
columns: [{ header: 'Value', width: 1, dataIndex: this.displayField }],
hideHeaders: true
});
Can be something like this:
this.view = new Ext.ListView({
multiSelect: true,
store: this.store,
columns: [{ xtype: 'templatecolumn',
header: 'Value',
width: 1,
tpl: new Ext.XTemplate(
'<tpl if="removed==true">',
'<div class="removed">{' + this.displayField + '}</div>',
'<tpl else>',
'<div>{' + this.displayField + '}</div>',
'</tpl>'
)
}],
hideHeaders: true
});
or you can modify it after rendering... your choice :)