extjs4 store动态列

今天项目遇到一个问题,需要使用extjs4 的grid的动态列,即列表的列需要根据需要动态的生成。

思路:定义grid时,columns根据配置获取,store中model的fields也根据配置动态获取。但是发现store中model的fields是很难改变的,因为很难拿到model对象,来执行model.setFields()方法。经过查看AbstractStore的源码发现,extjs4为了兼容extjs3当store中不给配置model属性,而配置了fields属性的时候,store会默认生成一个ImplicitModel。所以要实现动态的列,只需给store配置动态proxy(对应不同的url)、和动态的fields即可。

(只需关注标红的代码和添加了注释的代码即可,其它的代码是方便我日后参考)

AbstractStore生成自定义model的代码如下:

 //Supports the 3.x style of simply passing an array of fields to the store, implicitly creating a model
        if (!me.model && me.fields) {
            me.model = Ext.define('Ext.data.Store.ImplicitModel-' + (me.storeId || Ext.id()), {
                extend: 'Ext.data.Model',
                fields: me.fields,
                proxy: me.proxy || me.defaultProxyType
            });

            delete me.fields;

            me.implicitModel = true;
        }

定义的store代码如下:

Ext.define('shinow.ux.drugSearch.DrugSearchComboStore', {
	extend : 'Ext.data.Store',
	constructor : function(cfg) {
		var me = this;
		cfg = cfg || {};
		me.callParent([Ext.apply({}, cfg)]);
	}
});

定义的combobox的代码如下:

Ext.require('shinow.shinow.ux.field.GridComboBox');
Ext.define('shinow.ux.drugSearch.DrugSearchCombo', {
	extend : 'shinow.ux.field.GridComboBox' ,
	requires : ['shinow.shinow.ux.drugSearch.DrugSearchComboStore'],
	alias : 'widget.drugSearchCombo',
	constructor : function(cfg) {
		var me = this;
		cfg = cfg || {};
		me.callParent([
			Ext.apply({
				contentWidth : 500,
				contentHeight : 400,
				pageSize : 15,
				queryMode : 'remote',
				minChars : 2
			},cfg)
		]);
	}
	,
	initComponent : function() {
		var me = this;
		var proxy = {
				type : 'ajax',
				url : me.url,//动态配置url
				actionMethods : {
					create : "POST",
					read : "POST",
					update : "POST",
					destroy : "POST"
				},
				reader : {
					type : 'json',
					root : 'resultData.data',
					totalProperty : 'resultData.totalProperty'
				}
			};
		if(me.url && me.fields) {
		        //此处将动态的配置信息传入store中,实现动态列。proxy提供数据源,fields实现表格的列
			me.store = Ext.create('shinow.ux.drugSearch.DrugSearchComboStore',{proxy : proxy ,fields : me.fields});
		}else {
			Ext.Msg.alert('警告','请配置控件的url和fields属性!');
		}
		me.callParent(arguments);
	}
});

下拉grid  GridComboBox  代码如下:

Ext.define("shinow.ux.field.GridComboBox", {
    extend: "Ext.form.field.ComboBox",
    alias: ["widget.gridcombobox", "widget.gcombobox", "widget.gcombo"],
    requires: ["shinow.shinow.ux.grid.GridList", "shinow.shinow.ux.grid.GridListKeyNav"],
    contentWidth: 400,
    contentHeight: 400,
    queryCaching: false,
    matchFieldWidth: false,
    initComponent: function() {
        var a = this;
        if (!a.queryMode || a.queryMode == "remote") {
            if (!a.triggerAction || a.triggerAction == "all") {
                a.triggerAction = "query"
            }
        }
        a.callParent()
    },
    onmouseupEvn: function(c, b, a) {
        c.stopEvent();
        if (this.editable) {
            this.inputEl.focus()
        }
    },
    createPicker: function() {
        var c = this;
        var d = [{
            xtype: "rownumberer",
            resizable: true
        }];
        if (c.columns) {
            d = d.concat(c.columns)
        }
        if (!c.listConfig) {
            c.listConfig = {}
        }
        c.listConfig.columns = d;
        var b, a = Ext.apply({
            xtype: "gridlist",
            pickerField: c,
            selModel: {
                mode: c.multiSelect ? "SIMPLE" : "SINGLE"
            },
            border: false,
            height: c.contentHeight,
            width: c.contentWidth,
            cls: "x-boundlist",
            floating: true,
            hidden: true,
            store: c.store,
            displayField: c.displayField,
            focusOnToFront: false,
            pageSize: c.pageSize
        }, c.listConfig, c.defaultListConfig);
        b = c.picker = Ext.widget(a);
        if (c.pageSize) {
            b.pagingToolbar.on("beforechange", c.onPageChange, c)
        }
        c.mon(b, {
            itemclick: c.onItemClick,
            refresh: c.onListRefresh,
            scope: c
        });
        c.mon(b.getSelectionModel(), {
            beforeselect: c.onBeforeSelect,
            beforedeselect: c.onBeforeDeselect,
            selectionchange: c.onListSelectionChange,
            scope: c
        });
        var h = c.valueModels || [],
            g = h.length,
            i, f;
        var e = [];
        for (i = 0; i < g; i++) {
            f = h[i];
            if (f && f.isModel && c.store.indexOf(f) >= 0) {
                e.push(f)
            }
        }
        if (e.length) {
            b.show();
            b.getView().getSelectionModel().select(e, undefined, true)
        }
        c.mon(c.inputEl, "mousedown", c.onmouseupEvn, c);
        return b
    },
    getSelMode: function() {
        return this.valueModels
    },
    onExpand: function() {
        var d = this,
            a = d.listKeyNav,
            c = d.selectOnTab,
            b = d.getPicker();
        if (a) {
            a.enable()
        } else {
            a = d.listKeyNav = new shinow.ux.grid.GridListKeyNav(this.inputEl, {
                gridList: b,
                forceKeyDown: true,
                tab: function(f) {
                    if (c) {
                        this.selectHighlighted(f);
                        d.triggerBlur()
                    }
                    return true
                },
                enter: function(h) {
                    var f = b.getSelectionModel(),
                        g = f.getCount();
                    this.selectHighlighted(h);
                    if (!d.multiSelect && g === f.getCount()) {
                        d.collapse()
                    }
                }
            })
        }
        if (c) {
            d.ignoreMonitorTab = true
        }
        Ext.defer(a.enable, 1, a);
        d.inputEl.focus()
    },
    doAutoSelect: function() {
        var b = this,
            a = b.picker,
            c, d;
        if (a && b.autoSelect && b.store.getCount() > 0) {
            c = a.getSelectionModel().lastSelected;
            d = a.getView().getNode(c || 0);
            if (d) {
                a.getView().highlightItem(d);
                a.getView().getTargetEl().scrollChildIntoView(d, false)
            }
        }
    },
    alignPicker: function() {
        var b = this,
            a = b.getPicker();
        if (b.isExpanded) {
            if (b.matchFieldWidth) {
                a.setWidth(b.bodyEl.getWidth())
            }
            if (a.isFloating()) {
                b.doAlign()
            }
        }
    },
    onTriggerClick: function() {
        var a = this;
        if (!a.readOnly && !a.disabled) {
            if (a.isExpanded) {
                a.collapse()
            } else {
                a.onFocus({});
                if (a.triggerAction === "all") {
                    a.doQuery(a.allQuery, true)
                } else {
                    if (a.triggerAction === "last") {
                        a.doQuery(a.lastQuery, true)
                    } else {
                        a.doQuery(a.getRawValue(), true, true)
                    }
                }
            }
            a.inputEl.focus()
        }
    },
    doRemoteQuery: function(b) {
        var c = this,
            a = function() {
                c.afterQuery(b)
            };
        if (c.pageSize) {
            c.loadPage(1, {
                rawQuery: b.rawQuery,
                callback: a
            })
        } else {
            c.store.load({
                params: c.getParams(b.query),
                rawQuery: b.rawQuery,
                callback: a
            })
        }
        c.expand()
    }
});

GridList代码如下:

Ext.define("shinow.ux.grid.GridList", {
    extend: "Ext.panel.Table",
    requires: ["Ext.grid.View"],
    alias: ["widget.gridlist"],
    alternateClassName: ["Ext.list.ListView", "Ext.ListView", "Ext.grid.GridPanel"],
    viewType: "gridview",
    lockable: false,
    rowLines: true,
    deferRowRender: false,
    columnLines: true,
    initComponent: function() {
        var a = this;
        a.callParent();
        if (a.pageSize) {
            a.pagingToolbar = a.createPagingToolbar();
            a.addDocked(a.pagingToolbar)
        }
    },
    createPagingToolbar: function() {
        return Ext.widget("pagingtoolbar", {
            id: this.id + "-paging-toolbar",
            pageSize: this.pageSize,
            store: this.store,
            dock: "bottom",
            displayInfo: true,
            border: false,
            ownerCt: this,
            ownerLayout: this.getComponentLayout()
        })
    }
});

GridListKeyNav代码如下:

Ext.define("shinow.ux.grid.GridListKeyNav", {
    extend: "Ext.util.KeyNav",
    requires: "shinow.shinow.ux.grid.GridList",
    constructor: function(b, a) {
        var c = this;
        c.gridList = a.gridList;
        c.callParent([b, Ext.apply({}, a, c.defaultHandlers)])
    },
    defaultHandlers: {
        up: function() {
            var e = this,
                b = e.gridList,
                d = b.getView().all,
                f = b.getView().highlightedItem,
                c = f ? b.getView().indexOf(f) : -1,
                a = c > 0 ? c - 1 : d.getCount() - 1;
            e.highlightAt(a)
        },
        down: function() {
            var e = this,
                b = e.gridList,
                d = b.getView().all,
                f = b.getView().highlightedItem,
                c = f ? b.getView().indexOf(f) : -1,
                a = c < d.getCount() - 1 ? c + 1 : 0;
            e.highlightAt(a)
        },
        pageup: function() {},
        pagedown: function() {},
        home: function() {
            this.highlightAt(0)
        },
        end: function() {
            var a = this;
            a.highlightAt(a.gridList.all.getCount() - 1)
        },
        enter: function(a) {
            this.selectHighlighted(a)
        }
    },
    highlightAt: function(a) {
        var b = this.gridList,
            c = b.getView().all.item(a);
        if (c) {
            c = c.dom;
            b.getView().highlightItem(c);
            b.getView().getTargetEl().scrollChildIntoView(c, false)
        }
    },
    selectHighlighted: function(f) {
        var d = this,
            b = d.gridList,
            c = b.getView().highlightedItem,
            a = b.getSelectionModel();
        if (c) {
            a.selectWithEvent(b.getView().getRecord(c), f)
        }
    }
});

引用下拉列表的代码如下:\\这段代码就是如何使用自己定义的下拉列表类

{
	xtype : 'drugSearchCombo',
	fieldLabel :'药品查询',
	labelAlign : 'right',
	contentWidth : 500,
	contentHeight : 400,
	width : 200,
	pageSize : 15,
	queryMode : 'remote',
	minChars : 2,
	url : contentPath + '/chargeItem/queryChargeItemList.action',//动态配置url数据源地址
	fields : [//动态配置fields决定列表的列
		{
			//收费项目ID
			name : 'feeInfoID'
		}
		,{
			//收费项目类型ID
			name : 'feeTypeID'
		}
		,{
			//收费项目分类(主键ID)
			name : 'feeKindID'
		}
		,{
			//收费项目编码
			name : 'feeInfoCode'
		}
		,{
			//收费项目名称
			name : 'feeInfoName'
		}
	],
	columns : [//动态配置列表的列
		{
			text : '收费项目ID',
			dataIndex : 'feeInfoID',
			flex : 1
		}
		,{
			text : '收费项目类型ID',
			dataIndex : 'feeTypeID',
			flex : 1
		}
		,{
			text : '收费项目分类',
			dataIndex : 'feeKindID',
			flex : 1
		}
		,{
			text : '收费项目编码',
			dataIndex : 'feeInfoCode',
			flex : 1
		}
		,{
			text : '收费项目名称',
			dataIndex : 'feeInfoName',
			flex : 1
		}
	]
}

注意:使用需要在view中,通过requires方式,将控件引入

requires : ['shinow.shinow.ux.drugSearch.DrugSearchCombo']


你可能感兴趣的:(Model,store,fields,动态列)