Extjs6.2实现分组全选 利用标题添加checkbox

   自己研究许久未果,后来在领导的帮助下在google搜索下找到示例。现在extjs已经不再流行,网上面的例子都已经不再适用。

贴网址:https://fiddle.sencha.com/fiddle/19rr?height=600

效果如图:

 

原文的代码有几个bug,第一是不能使用grouping的startCollapsed属性。因为原来的TPL渲染的视图会在再次渲染的过程中破坏。下文代码我会标注出来,目前发现的bug均已修复。

原文的选中逻辑只能使用{xtype: 'checkcolumn', dataIndex:'isChecked'}的方式,后续我添加了兼容设置grid的selModel: {type: 'checkboxmodel'}的方式,但是此方式我没有直接使用(由于原作者的代码里面大部分用了checkDataIndex: 'isChecked'来做逻辑处理),因此使用者请注意可能出现bug。

 

 

/*************************************************
 * author :  unknown Netizen
 * function: CheckboxGroupingFeature
 * history:  created by MrJGuo 2019/5/31 17:58
 * warn:引用的grid请使用checkboxmodel模式(selModel: {type: 'checkboxmodel'})
 *              或者定义第一行{xtype: 'checkcolumn', dataIndex:'isChecked'}
 * forExample :
 * Ext.create('Ext.grid.Panel', {
    title: 'Employees',
    store: store,
    selModel: {
                type: 'checkboxmodel',
            },
    columns: [ {
        text: 'Name',
        dataIndex: 'name'
    }, {
        text: 'Seniority',
        dataIndex: 'seniority'
    }],
    features: [{
        ftype: 'checkboxGrouping',
        enableGroupingMenu: false,
        hideGroupHeader: true
    }],
    width: 500,
    height: 600,
    renderTo: Ext.getBody()
});
 *************************************************/
Ext.define('SDE.ux.field.CheckboxGroupingFeature', {
    extend: 'Ext.grid.feature.Grouping',
    alias: 'feature.checkboxGrouping',

    /** @property */
    targetCls: 'group-checkbox',
    /** @property */
    checkDataIndex: 'isChecked',
    startCollapsed: true,

    constructor: function(config) {
        //此处原文没有判断values.record为空的情况 因此startCollapsed属性设置视图会出现问题
        config.groupHeaderTpl = ['<input class="' + this.targetCls + '" {[values.record ? values.record.get("' + this.checkDataIndex + '") ? "checked" : "" :""]} type="checkbox"> {name}'];
        this.callParent(arguments);
    },

    init: function(grid) {
        var store = grid.getStore();
        if (store) {
            store.on('update', this.onStoreUpdate, this);
        }
        this.callParent(arguments);
    },

    setupRowData: function(record, idx, rowValues) {
        this.callParent(arguments);
        // Ext JS 6 vs Ext JS 5.1.1 vs Ext JS 5.1.0-
        var groupInfo = this.groupRenderInfo || this.metaGroupCache || this.groupInfo;
        groupInfo.record = this.getParentRecord(record.get(this.getGroupField()));
    },

    /**
     * This method will only run once... on the initial load of the view... this
     * is so we can check the store for the grouped item's children... if they're
     * all checked, then we need to set the private variable to checked
     */
    checkAllGroups: function(groupName) {
        var store = this.view.getStore();
        var groupField = this.getGroupField();
        if (store) {
            var groups = store.getGroups();
            if (groups) {
                groups.each(function(groupRec) {
                    var allChecked = true;
                    var groupKey = groupRec.getGroupKey();
                    var checkGroup = true;
                    if (groupName) {
                        if (groupKey !== groupName) {
                            checkGroup = false;
                        }
                    }
                    if (checkGroup) {
                        groupRec.each(function(rec) {
                            allChecked = rec.get(this.checkDataIndex);
                            groupName = rec.get(groupField);
                            if (allChecked === false) {
                                return false;
                            }
                        }, this);
                        this.updateParentRecord(groupName, allChecked);
                    }
                }, this);
            }
        }
    },

    updateParentRecord: function(groupName, checked,store) {
        var parentRecord = this.getParentRecord(groupName,store);
        if (parentRecord) {
            parentRecord.set(this.checkDataIndex, checked);
            this.refreshView();
        }
    },

    getParentRecord: function(groupName,store) {
        var parentRecord;
        var metaGroup;
        // For Ext JS 6 and 5.1.1
        if (this.getMetaGroup) {
            metaGroup = this.getMetaGroup(groupName);
        }
        // For Ext JS 5.1-
        else {
            metaGroup = this.groupCache[groupName];
        }
        if (metaGroup) {
            if (metaGroup.placeholder) {
                //此处如果设置了startCollapsed为true,第一次渲染的时候是没有占位符的
                parentRecord = metaGroup.placeholder;
            } else {
                //手动添加占位符、第一次渲染的时候没有点击展开或者收缩 源码是没有做添加占位符的操作的
                parentRecord = this.addPlaceHolderByGroup(groupName,metaGroup,store);
            }

        }
        return parentRecord;
    },

    /**
     *  This might break... we're using a private variable here... but this
     * is the only way we can refresh the view without breaking any sort of
     * scrolling... I'm not sure how to only refresh the group header itself, so
     * I'm keeping the groupName as a param passing in... might be able to figure
     * this out later
     *
     * ###### Already perfected by MrJGuo  2019.6.24
     * @param {String} groupName
     */
    refreshView: function(groupName) {
        var view = this.view;
        if (view) {
            view.refreshView();
        }
    },

    onStoreUpdate: function(store, record, operation, modifiedFieldNames, details, eOpts) {
        var grid = this.grid;
        if (!this.updatingRecords && grid && record) {
            var groupName = record.get(this.getGroupField());
            this.checkAllGroups(groupName);
            grid.setSelection(record);
            this.refreshView(groupName);
        }
    },

    onGroupClick: function(grid, node, group, event, eOpts) {
        if (event && grid) {
            var target = event.getTarget('.' + this.targetCls);
            var store = grid.getStore();
            var groupRecord = this.getRecordGroup(event.record);
            var groupField = store .getGroupField();
            if (target && store && groupRecord && groupField) {
                var checked = target.checked;
                this.updatingRecords = true;
                if (grid.getColumnManager().columns[0].dataIndex === this.checkDataIndex) {
                    groupRecord.each(function(rec, index) {
                        rec.beginEdit();
                        rec.set(this.checkDataIndex, checked);
                        rec.endEdit(true);
                    }, this);
                } else if (grid.selModel.type === 'checkboxmodel') {
                    grid.getStore().each(function(rec, index){
                        if(rec.get(groupField) === group){
                            if (!checked) {
                                grid.getSelectionModel().deselect(index, true);
                            } else {
                                grid.getSelectionModel().select(index, true);
                            }
                        }
                    },this);
                }
                this.updatingRecords = false;
                this.updateParentRecord(group, checked,store);
            } else {
                this.callParent(arguments);
            }
        }
    },

    addPlaceHolderByGroup : function (groupName,metaGroup,store) {
        if (!store) {
            return;
        }
        if (!metaGroup.placeholder) {
            var Model = store.getModel(),
                modelData = {},
                key = groupName,
                groupPlaceholder;
            modelData[store.getGroupField()] = key;
            groupPlaceholder = metaGroup.placeholder = new Model(modelData);
            groupPlaceholder.isNonData = groupPlaceholder.isCollapsedPlaceholder = true;
            // Adding the groupKey instead of storing a reference to the group
            // itself. The latter can cause problems if the store is reloaded and the referenced
            // group is lost. See EXTJS-18655
            groupPlaceholder.groupKey = key;
        }
        return metaGroup.placeholder;
    }
});

使用方式已经在注释头描述清楚,后续有使用出现的bug再修改。刚入手extjs,如有不当之处还请指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值