最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ExtJS - Differentiate items in MultiSelect - Stack Overflow

programmeradmin3浏览0评论

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
Add a ment  | 

2 Answers 2

Reset to default 4 +150

For 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 :)

发布评论

评论列表(0)

  1. 暂无评论