[pve-devel] [PATCH pve-manager v2] ext6migrate: Update our ComboGrid component to work with ExtJS6

Emmanuel Kasper e.kasper at proxmox.com
Wed Jan 13 11:24:34 CET 2016


Instead of extending the framework ComboBox, we extend the abstract
parent class Picker, so we don't rely on private methods ( and hopefull survive the
next ExtJS upgrade )

Usability improvement:
The selection model is now a checkboxmodel, which makes more clear to the user that
we can select more than one element in the list.
---
 www/manager6/form/ComboGrid.js | 152 +++++++++++++++++++++++------------------
 1 file changed, 86 insertions(+), 66 deletions(-)

diff --git a/www/manager6/form/ComboGrid.js b/www/manager6/form/ComboGrid.js
index a226cb5..6bbb7cc 100644
--- a/www/manager6/form/ComboGrid.js
+++ b/www/manager6/form/ComboGrid.js
@@ -1,84 +1,104 @@
+/*
+ * ComboGrid component:
+ * a ComboBox where the dropdown menu (the "Picker") is a Grid with Rows and Columns
+ * expects a listConfig object with a columns property
+ * roughly based on the GridPicker from https://www.sencha.com/forum/showthread.php?299909
+ *
+*/
 Ext.define('PVE.form.ComboGrid', {
-    extend: 'Ext.form.field.ComboBox',
+    extend: 'Ext.form.field.Picker',
     alias: ['widget.PVE.form.ComboGrid'],
 
     // this value is used as default value after load()
     preferredValue: undefined,
-
-    // hack: allow to select empty value
-    // seems extjs does not allow that when 'editable == false'
-    onKeyUp: function(e, t) {
-        var me = this;
-        var key = e.getKey();
-
-        if (!me.editable && me.allowBlank && !me.multiSelect &&
-	    (key == e.BACKSPACE || key == e.DELETE)) {
-	    me.setValue('');
-	}
-
-        me.callParent(arguments);	
+    // If set to `true`, allows the combo field to hold more than one value at a time, and allows selecting multiple
+    // items from the dropdown list.
+    multiSelect: false,
+
+    defaultPickerConfig: {
+        maxHeight: 300,
+        width: 400,
+        scrollable: true,
+        floating: true,
     },
 
-    // copied from ComboBox 
-    createPicker: function() {
-        var me = this,
-        picker,
-        menuCls = Ext.baseCSSPrefix + 'menu',
+    displayField: false,
+    valueField: false,
+    matchFieldWidth: false,
 
-        opts = Ext.apply({
+    createPicker: function() {
+	var me = this;
+        var config = Ext.applyIf({
+            store: me.getStore(),
             selModel: {
-                mode: me.multiSelect ? 'SIMPLE' : 'SINGLE'
+                selType: 'checkboxmodel',
+                mode: me.multiSelect ? 'SIMPLE' : 'SINGLE',
+                showHeaderCheckbox: false // shows a selectAll checkbox, not reliable
             },
-            floating: true,
-            hidden: true,
-            ownerCt: me.ownerCt,
-            cls: me.el.up('.' + menuCls) ? menuCls : '',
-            store: me.store,
-            displayField: me.displayField,
-            focusOnToFront: false,
-            pageSize: me.pageSize
-        }, me.listConfig, me.defaultListConfig);
-
-	// NOTE: we simply use a grid panel
-        //picker = me.picker = Ext.create('Ext.view.BoundList', opts);
-	picker = me.picker = Ext.create('Ext.grid.Panel', opts);
-
-	// pass getNode() to the view
-	picker.getNode = function() {
-	    picker.getView().getNode(arguments);
-	};
-
-        me.mon(picker, {
-            itemclick: me.onItemClick,
-            refresh: me.onListRefresh,
-	    show: function() {
-		me.syncSelection();
-	    },
-            scope: me
-        });
-
-        me.mon(picker.getSelectionModel(), 'selectionchange', me.onListSelectionChange, me);
-
-        return picker;
+            listeners: {
+                selectionchange: {
+                    fn: function(grid, selectedRecords) {
+                        me.setRecords(selectedRecords);
+                        me.fireEvent('select', me, selectedRecords);
+                    },
+                    scope: me
+                }
+            }
+        }, me.defaultPickerConfig);
+
+        var grid = Ext.create('Ext.grid.Panel', config);
+
+        // update the grid with the field values when loading
+        if (me.getRawValue()){
+            var previousItems = [];
+            Ext.Array.each(me.getRawValue().split(','), function(record) {
+                var previousItem = me.store.findRecord(me.valueField, record);
+                previousItems.push(previousItem);
+            });
+
+            grid.getSelectionModel().select(previousItems);
+
+        }
+
+        return grid;
     },
 
-    initComponent: function() {
-	var me = this;
+    setRecords: function(records) {
+        if (records && !Ext.isArray(records)) {
+            records = [records];
+        }
+        this.selectedRecords = records;
+        var rawValue = [];
 
-	if (me.initialConfig.editable === undefined) {
-	    me.editable = false;
-	}
+        Ext.Array.each(records, function(record) {
+            rawValue.push(record.get(this.displayField));
+        }, this);
 
-	Ext.apply(me, {
-	    queryMode: 'local',
-	    matchFieldWidth: false
-	});
+        this.setValue(rawValue);
+    },
+
+    getRecords: function() {
+        return this.selectedRecords;
+    },
 
-	Ext.applyIf(me, { value: ''}); // hack: avoid ExtJS validate() bug
+    beforeReset: function() {
+        if(this.picker) {
+            this.picker.getSelectionModel().deselectAll()
+        }
+        this.callParent(arguments);
+    },
 
-	Ext.applyIf(me.listConfig, { width: 400 });
+    getStore: function() {
+        if (!this.store) {
+            this.store = Ext.create('Ext.data.Store', {});
+        }
+        return this.store;
+    },
 
-        me.callParent();
+    initComponent: function() {
+	var me = this;
+	Ext.apply(me.defaultPickerConfig, me.listConfig);
+        me.callParent(arguments);
 
 	me.store.on('beforeload', function() {	 
 	    if (!me.isDisabled()) {
@@ -126,5 +146,5 @@ Ext.define('PVE.form.ComboGrid', {
 		}
 	    }
 	});
-    }
-});
+    },
+});
\ No newline at end of file
-- 
2.1.4





More information about the pve-devel mailing list