ExtJS - 区分 MultiSelect 中的项目

3
我在一个表单面板中有两个多选框,它们被放置在一个项目选择器中。每个多选框由两个存储区组成:左侧和右侧(带有箭头移动项目)。
当我加载面板时,我提供一个引用,以突出从一侧移到另一侧的项目(例如,将已移动项目设置为红色样式),因为今天没有办法区分它们。
我成功地捕获了“afterAdd”事件,在存储库上应用我的样式,通过DOM访问来实现。这在跟踪期间有效,但稍后执行剩余的ExtJS标准调用,覆盖了我刚刚应用的样式...
我觉得我做的不好,但我对ExtJS还很陌生,所以有点迷茫...谢谢你的帮助!
编辑:这里是我的代码示例,我忘记告诉你我是在ExtJS 3.2上工作的(嗯...)。 "pool_cnx_to_rule"是我的表单面板:
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();
        }
    }
});

哈哈 :) Ext 3.2,你在这里忘记提到的小细节 :) - VDP
是的,抱歉,我目前正在为此自责。 - Emmanuel
2个回答

4

针对Ext 4.2

这里有一个示例,它可以为您选择的记录着色。(使用它,选择一些项目然后按“红色”按钮即可…) 它不处理添加和捕获事件,仅处理所选项目的着色。据我理解,这是您觉得有问题的部分。

基本上,我向multiSelection添加了一个listConfig,该listConfig将其转移到其boundList中:

listConfig: {
    itemTpl: '<div class="my-boundlist-item {color}">{numberName}</div>',
} 

模板从多选存储获取其值,因此我们只需为要记录的“颜色”字段设置值:
myRecord.set('color', 'red');

通过这样做,我们设置的项目现在将具有类名“red”。最后一件事是为该类添加CSS:
.red {
    background-color: rgba(255,0,0,0.2);
}

请注意,我让它非常透明,因此选择和悬停颜色仍然可见。
对于Ext3.2,
这是一个演示链接。正如@VDP所提到的,Ext 3.2使用ListView进行多选,该列表可以获取tpl配置(实际上,templatecolumn对于listview不可用,只适用于grid)。
但是MultiSelect没有公开此配置,因此我们必须覆盖multiselect的onRender方法,在此处显示有趣的部分:
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
        });
        ...

现在我们可以使用扩展类将listItemTpl配置项传递给视图:
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>',
}],

其余部分与Ext 4.2基本相同。

哇,令人印象深刻!我仔细研究了你的解决方案,因为我使用的是3.x版本,MultiSelect的使用方式有点不同(在ItemSelector中,查看我的编辑代码),所以我认为我不能指定一个id以后再处理它。我是对的吗? - Emmanuel
不,你不能在Ext 3.2中使用我的解决方案,但是正如@VDP所指出的那样,他的更新指向了正确的方向。如果我今天有时间,我可能会为3.2实现一个fiddle。谢谢 :) - Amit Aviv
使用Ext 3.2的实现进行编辑。 - Amit Aviv
好了,现在不远了:我编辑了我的帖子,向您展示了我的代码的最后状态。设置颜色可以工作,但是...这会复制所显示的项目(并且在跟踪期间也在“fs”对象中重复)!!! 我尝试从“fs”中删除元素(pools_selected_.fs.items.clear()),但这行不通。我还尝试使用本地视图而不是将其分配给我的“MultiSelect”,但这也不起作用。 - Emmanuel
回答一个问题,你可能会问:如果我像在这个fiddle中一样覆盖了fsvar fs = pools_selected_.fs = new Ext.form.FieldSet...),那么什么都不会发生(没有颜色变化,也没有重复)。 - Emmanuel
显示剩余3条评论

3

我不太清楚你希望何时进行标记。

我的做法是在fromField和/或toField的存储上附加一个监听器。

假设我们希望将从toField中删除的所有项目都标记:

// 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

这不是一个现成的解决方案,但或许可以帮助你找到正确的方向...

更新:

@Amit Aviv 刚刚详细说明了我所说的“更改”itemTpl以添加一个类的意思。

我想做的是类似于这样的事情:

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>'
    )
}

其他部分保持不变。阿米特的解决方案同样也很好 ;)
在 Ext 3 中,选择器包含2个 Ext.ux.form.MultiSelect。一个 MultiSelect 包含一个 Ext.ListView,在 Ext 4 中使用 BoundList。这个 ListView 非常类似于一个网格。
它没有 itemTpl,但有列。您可以重写 MultiSelect 的 onRender 方法,以便在 ListView 中插入自己的列。这是要修改的部分:
this.view = new Ext.ListView({
    multiSelect: true,
    store: this.store,
    columns: [{ header: 'Value', width: 1, dataIndex: this.displayField }],
    hideHeaders: true
});

可以像这样:

可以是这样的:

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
});

或者你可以在渲染后进行修改......这是你的选择 :)

谢谢,我的第一个答案 :-) 我可能确实不太清楚。对我来说计算差异没有问题 - 我只是不能将不同的样式应用于从原始版本更改的项目。 - Emmanuel
我按照Amit的建议做了,即重写自定义MultiSelect的onRender函数,但是在将一个项目从一个MultiSelect移动到另一个MultiSelect的过程中,似乎从未调用此方法(我使用Firebug和断点)。 - Emmanuel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接