ExtJs的grid功能很強大,可是有時候以爲老是少那麼一點點功能,咱們就來擴展它,讓它用起來更方便。css
今天咱們要擴展的是:根據記錄的選擇數量來禁用或啓用grid toolbar上的某些按鈕。git
本文全部的代碼和例子都在個人github上:ExtJsExtendgithub
在開始以前,咱們先來擴展ExtJs的container容器。數組
在ExtJs中,能夠經過給組件分配一個id來標識它,id是一個全局的惟一的標識,而後經過Ext.getCmp(id)來獲取這個組件,看起來很方便,可是在單頁應用中,給組件一個惟一的全局id名是很傷腦筋的事情。ExtJs也考慮到了這種狀況,就弄了一個itemId,這個不須要全局惟一,只要在同一個container中惟一就能夠了,而且也提供了一個方法經過itemId獲取組件:container.getComponent(itemId),其實這個方法的參數不單單是支持itemId,也能夠傳入全局惟一的id或者組件在container中的位置來獲取該組件。app
可是對於咱們來講,仍是有那麼一點點不方便,好比在一個form中,有fieldContainer或者fieldSet,經過form.getComponet(),只能獲取form的直接child,不能獲取到form中嵌套的container下的child,這樣只能經過form先找到嵌套的container,而後再調用該container的getComponet方法獲取到須要的組件,這在一個複雜佈局的form中(好比在fieldSet中又嵌套fieldContainer)操做起來就更加不方便了。ide
等等,container不是有一個items屬性嗎?這裏是否能夠獲取到跨級的組件呢?很遺憾,這個items集合也只是包含了直接的child。佈局
咱們的解決方案就是allItems,從名稱上就能看出來,allItems就是包含就是包含全部直接或嵌套(不限層級)的child(其實也不是全部的child,後面的代碼中能夠看到)。flex
實現方法很簡單:給container一個allItems的屬性,而後重載container的onAdd和onAdded方法,注意這兩個的區別,onAdd是有組件加入到這個容器中的時候被調用,onAdded是本身(container本身首先也是一個組件)被加入到某個container的時候被調用,代碼很簡單,直接貼出代碼: this
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]; } } } } });
須要說明的是:spa
先上一組效果圖:
當沒有記錄被選中的時候Edit和Delete按鈕都是disabled的。
當有一條記錄被選中的時候,Edit和Delete都啓用了。
當有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