zoukankan      html  css  js  c++  java
  • ExtJS扩展:扩展grid

    ExtJs的grid功能很强大,但是有时候觉得总是少那么一点点功能微笑,我们就来扩展它,让它用起来更方便。

    今天我们要扩展的是:根据记录的选择数量来禁用或启用grid toolbar上的某些按钮

    本文所有的代码和例子都在我的github上:ExtJsExtend

    开始之前

    在开始之前,我们先来扩展ExtJs的container容器。

    在ExtJs中,可以通过给组件分配一个id来标识它,id是一个全局的唯一的标识,然后通过Ext.getCmp(id)来获取这个组件,看起来很方便,但是在单页应用中,给组件一个唯一的全局id名是很伤脑筋的事情。ExtJs也考虑到了这种情况,就弄了一个itemId,这个不需要全局唯一,只要在同一个container中唯一就可以了,并且也提供了一个方法通过itemId获取组件:container.getComponent(itemId),其实这个方法的参数不仅仅是支持itemId,也可以传入全局唯一的id或者组件在container中的位置来获取该组件。

    但是对于我们来说,还是有那么一点点不方便,比如在一个form中,有fieldContainer或者fieldSet,通过form.getComponet(),只能获取form的直接child,不能获取到form中嵌套的container下的child,这样只能通过form先找到嵌套的container,然后再调用该container的getComponet方法获取到需要的组件,这在一个复杂布局的form中(比如在fieldSet中又嵌套fieldContainer)操作起来就更加不方便了。

    等等,container不是有一个items属性吗?这里是否可以获取到跨级的组件呢?很遗憾,这个items集合也只是包含了直接的child。

    我们的解决方案就是allItems,从名称上就能看出来,allItems就是包含就是包含所有直接或嵌套(不限层级)的child(其实也不是所有的child,后面的代码中可以看到)。

    实现方法很简单:给container一个allItems的属性,然后重载container的onAdd和onAdded方法,注意这两个的区别,onAdd是有组件加入到这个容器中的时候被调用,onAdded是自己(container自己首先也是一个组件)被加入到某个container的时候被调用,代码很简单,直接贴出代码:

    Ext.define('Ext.container.ContainerOverride', { 
        override: 'Ext.container.Container', 
        initComponent: function () { 
            var me = this; 
            Ext.applyIf(me, { 
                allItems: {}, 
                preventItemsBubble: true 
            }); 
            me.callParent(); 
        }, 
        onAdd: function (cmp) { 
            var me = this; 
            me.callParent(arguments); 
            var name = cmp.itemId || cmp.name; 
            if (name) { 
                if (me.allItems[name]) { 
                    me.allItems[name] = Ext.Array.merge( 
                        Ext.Array.from(me.allItems[name]), 
                        [cmp]); 
                } 
                else { 
                    me.allItems[name] = cmp; 
                } 
            } 
        }, 
        onAdded: function (container) { 
            var me = this; 
            me.callParent(arguments); 
            if (container && me.preventItemsBubble !== true) { 
                for (var name in me.allItems) { 
                    if (container.allItems[name]) { 
                        container.allItems[name] = Ext.Array.merge( 
                            Ext.Array.from(container.allItems[name]), 
                            Ext.Array.from(me.allItems[name])); 
                    } 
                    else { 
                        container.allItems[name] = me.allItems[name]; 
                    } 
                } 
            } 
        } 
    }); 
     
     
    

    需要说明的是:

    1. 1. allItems是一个object,不是一个数组,通过组件的itemId或name(因为在form中field大多都有name,这样就不需要定义itemId了)来索引,itemId优先 。(嗯,之前说了其实并不是ALL)
    2. 2. itemId不在同一个container中可以重复,name可以在同一个container重复,如果有重复的itemId或name,那么allItems[itemId]获取到的将是一个数组
    3. 3. preventItemsBubble属性是为了阻止将allItems向上级冒泡,比如在一个form中,只要form能够获取到allItems就可以了,form的上级就没有必要知道这些items了,默认是阻止的,所以要在form的fieldContainer等中将其设置成false,fieldContainer等中的allItems才能冒泡到form的allItems中

    扩展grid之toolbar的按钮

    先上一组效果图:

    image

    当没有记录被选中的时候Edit和Delete按钮都是disabled的。

    image

    当有一条记录被选中的时候,Edit和Delete都启用了。

    image

    当有2条或以上的记录被选中的时候,Edit被禁用了(因为设计的时候要求只能同时编辑一条记录)。

    在前面的效果图中看到New始终是可以使用的,因为新建和选不选中记录都没有关系。

    其实这个效果实现起来很简单,无非就是监听selectionchange事件,然后根据选中的记录数来disable掉对应的按钮即可,但是如果有很多grid都要这样做是不是就变成了拷贝粘贴然后修改代码,自然我们就想到了重用,先看看我们这个例子的代码:

                Ext.create('Ext.grid.Panel', { 
                    title: 'Simpsons', 
                    store: Ext.data.StoreManager.lookup('simpsonsStore'), 
                    noSelectionDisable:['Edit','Delete','Print'], 
                    moreSelectionsDisable:['Edit'], 
                    selModel: Ext.create('Ext.selection.CheckboxModel', { allowDeselect: true }), 
                    tbar: { 
                        xtype: 'toolbar', 
                        preventItemsBubble: false, 
                        items: [ 
                            { 
                                xtype: 'button', 
                                itemId: 'Edit', 
                                text: 'Edit'}, 
                            { 
                                xtype: 'button', 
                                name: 'Delete', 
                                text: 'Delete'} 
                        ]}, 
                    dockedItems: [ 
                        { 
                            xtype: 'toolbar', 
                            preventItemsBubble: false, 
                            dock: 'right', 
                            items: [ 
                                { 
                                    xtype: 'button', 
                                    name: 'New', 
                                    text: 'New'}, 
                                { 
                                    xtype: 'button', 
                                    itemId: 'Edit', 
                                    text: 'Edit'}] 
                        } 
                    ], 
                    columns: [ 
                        { text: 'Name', dataIndex: 'name' }, 
                        { text: 'Email', dataIndex: 'email', flex: 1 }, 
                        { text: 'Phone', dataIndex: 'phone' } 
                    ], 
                    height: 200, 
                     400, 
                    renderTo: Ext.getBody() 
                }); 

    代码中可以看到有2个配置参数是ExtJs grid中没有,这就是我们扩展的:

    noSelectionDisable:['Edit','Delete','Print'],

    moreSelectionsDisable:['Edit'],

    noSelectionDisable就是告诉grid如果没有记录被选中,那就禁用这些名称(itemId)的按钮。

    moreSelectionsDisable就是告诉grid如果有超过2条的记录被选中,那么就禁用这些名称(itemId)的按钮。

    在源代码中找找,这些name在哪里?对,就是tbar和dockedItems中定义的button的名称(itemId)。这样使用grid是不是很简单了?

    这就是grid的扩展代码:

    Ext.define('Ext.ux.grid.PanelOverride', { 
        override: 'Ext.grid.Panel', 
        initComponent: function () { 
            var me = this; 
            me.on('selectionchange', me.onSelectionChange, me); 
            me.callParent(); 
        }, 
        onSelectionChange: function (grid, records) { 
            if (!records) { 
                return; 
            } 
            var me = this; 
            var items = me.allItems; 
            var disableNames = me.noSelectionDisable; 
            if (records.length == 1) { 
                disableNames = me.oneSelectionDisable; 
            } 
            if (records.length > 1) { 
                disableNames = me.moreSelectionsDisable; 
            } 
            for (var name in items) { 
                var item = items[name]; 
                if (Ext.isArray(item)) { 
                    Ext.Array.each(item, function (oneItem) { 
                        if (oneItem.enable) { 
                            oneItem.enable(); 
                        } 
                    }); 
                } 
                else if (item.enable) { 
                    item.enable(); 
                } 
                if (disableNames && Ext.Array.contains(disableNames, name)) { 
                    if (Ext.isArray(item)) { 
                        Ext.Array.each(item, function (oneItem) { 
                            if (oneItem.disable) { 
                                oneItem.disable(); 
                            } 
                        }); 
                    } 
                    else if (item.disable) { 
                        item.disable(); 
                    } 
                } 
            } 
        } 
    }); 
    

    在代码中可以看到,正是利用了之前扩展的allItems,所以能方便地获得grid toolbar中的按钮,使得代码非常精简了。

    希望能对使用ExtJs的朋友有帮助,谢谢。

    所有代码和例子在我的github上:ExtJsExtend

  • 相关阅读:
    java在线聊天项目0.7版 连接多个客户端问题,开启多个客户端后服务器端只接收到一个 对各种异常的补充处理
    java在线聊天项目0.6版 解决客户端关闭后异常问题 dis.readUTF()循环读取已关闭的socket
    指针 引用 举例:通过指针变量访问整型变量
    字符串数组 输入3个字符串,要求按由小到大的字母顺序输出; 输入n个学生的姓名和学号到字符串数组中,在输入一个姓名,如果班级有该生则返回其信息,否则返回本班无此人
    java在线聊天项目0.5版 解决客户端向服务器端发送信息时只能发送一次问题 OutputStreamWriter DataOutputStream socket.getOutputStream()
    java在线聊天项目0.4版本 制作服务端接收连接,客户端连接功能 新增客户端窗口打开时光标指向下边文本域功能,使用WindowListener监听WindowAdapter
    java在线聊天项目0.3版本 制作客户端窗体,实现发送按钮和回车发送信息功能,使用ActionListener监听事件中actionPerformed方法(用内部类和匿名内部类两种方法)
    java在线聊天项目0.2版本 制作客户端窗体,使用swing(用户界面开发工具包)和awt(抽象窗口工具包) BorderLayout布局与GridLayout布局不同之处 JPanel设置大小
    java在线聊天项目0.1版本 制作客户端窗体,使用swing(用户界面开发工具包)和awt(抽象窗口工具包)
    HashCode的作用原理和实例解析
  • 原文地址:https://www.cnblogs.com/tubo/p/3417782.html
Copyright © 2011-2022 走看看