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, 
                width: 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM