读书人

Ext JS 四 主从表

发布时间: 2012-09-20 09:36:50 作者: rapoo

Ext JS 4 主从表

Model

定义三个model

    /** * 对应Struts2中action的model */Ext.define('PriceAreaAction', { extend : 'Ext.data.Model', fields : [ 'priceArea', 'updatePriceEntrys', 'createPriceEntrys', 'deletePriceEntrys', 'message' ], proxy : { type : 'ajax', api : { create : 'savePriceArea.action', update : 'updatePriceArea.action' }, writer : { type : 'json' }, reader : { type : 'json' } }}); /** * PriceArea的Model */Ext.define('priceAreaModel', { extend : 'Ext.data.Model', fields : [ 'id', 'areaCode', 'areaName', 'createUser', { name : 'createDate', type : 'number' }, 'modifyUser', { name : 'modifyDate', type : 'number' } ], hasMany : { model : 'entryModel', name : 'entryList', foreignKey : 'areaId', associationKey : 'entryList', primaryKey : 'id', storeConfig : Ext.data.StoreManager.lookup('entryStore') }});/* * PriceEntry的Model */Ext.define('entryModel', { extend : 'Ext.data.Model', fields : [ 'id', 'areaId', { name : 'price', type : 'number' }, 'priceType', 'createUser', { name : 'createDate', type : 'number' }, 'modifyUser', { name : 'modifyDate', type : 'number' } ], belongsTo : { type : 'belongsTo', model : 'priceAreaModel', primaryKey : 'id', foreignKey : 'areaId' }});

    第一个model与服务器端的Action对应,后两个model与服务端的两个实体相似。在定义model的时候,也可以定义一对多的关系,在model中定义一个hasMany的属性,这个属性与服务端定义的List是一样的,它可以关联到另一个自定义的model,在这个hasMany中还要定义一个foreignKey,用于外键关联到另一个model对象上的上面的哪个属性。例子就是priceAreaModel关联到entryModel。

    Store

    定义两个Store,priceAreaStore用于得到区域的信息,entryStore用于得到区域价格信息

      var priceAreaStore = Ext.create('Ext.data.Store', { pageSize : 20, model : 'priceAreaModel', autoLoad : true, proxy : { type : 'ajax', actionMethods : 'post', url : 'queryPriceArea.action', reader : { type : 'json', root : 'priceAreaList', totalProperty : 'totalCount' } }});var entryStore = Ext.create('Ext.data.Store', { model : 'entryModel', storeId : 'entryStore', proxy : { url : 'queryPriceEntryByPriceAreaId.action', type : 'ajax', reader : { type : 'json', root : 'priceEntryList' } }});

      页面与操作

        Ext.require([ 'Ext.form.*', 'Ext.data.*', 'Ext.grid.Panel', 'Ext.layout.container.Column' ]); var priceAreaGrid = new Ext.grid.GridPanel({ border : false, autoScroll : true, store : priceAreaStore, columns : [ { id : 'id', hidden : true, dataIndex : 'id' }, { text : i18n('page.module.oneToMany.areaCode'), name:'areaCode', flex : 1, sortable : true, dataIndex : 'areaCode' }, { text : i18n('page.module.oneToMany.areaName'), name:'areaName', flex : 1, sortable : true, dataIndex : 'areaName' }, { text : i18n('page.module.oneToMany.createUser'), name:'createUser', flex : 1, sortable : true, dataIndex : 'createUser' }, { text : i18n('page.module.oneToMany.createDate'), name:'createDate', flex : 1, sortable : true, renderer : changeToDate, dataIndex : 'createDate' }, { text : i18n('page.module.oneToMany.modifyUser'), name:'modifyUser', flex : 1, sortable : true, dataIndex : 'modifyUser' }, { text : i18n('page.module.oneToMany.modifyDate'), name:'modifyDate', flex : 1, sortable : true, renderer : changeToDate, dataIndex : 'modifyDate' } ], width : window.screen.clientWidth * 0.998, height : window.screen.availHeight * 0.7, frame : true, tbar : [ { text : i18n('page.module.oneToMany.add'), handler : function() { createWin(new priceAreaModel()); } },{ text : i18n('page.module.oneToMany.update'), handler : function() { var sm = priceAreaGrid.getSelectionModel(); if (sm.getSelection().length > 0) { var record = sm.getSelection()[0]; entryStore.load({ params : { 'priceAreaId' : record.get("id") }, callback: function(records, operation, success) { if(success){ record.entryList().loadRecords(records,{}); createWin(record); } } }); } else { Ext.Msg.alert(i18n('page.module.oneToMany.message'), i18n('page.module.oneToMany.priceAreaGrid.message')); } } }, { text : i18n('page.module.oneToMany.delete'), handler : function() { var sm = priceAreaGrid.getSelectionModel(); var selection = sm.getSelection(); if (sm.getSelection().length > 0) { Ext.MessageBox.confirm(i18n('page.module.oneToMany.chick'),i18n('page.module.oneToMany.priceAreaGrid.chick_message'), function(btn) { if (btn == 'yes') { Ext.Ajax.request({ url : 'deletePriceArea.action', params : { 'priceAreaId' : selection[0].data.id }, success : function( response) { var json = Ext.decode(response.responseText); if (json.success == false) { Ext.MessageBox.alert(i18n('page.module.oneToMany.message'),json.message); } else { Ext.MessageBox.alert(i18n('page.module.oneToMany.message'),json.message); priceAreaStore.remove(selection); } }, failure : function(response) { var json = Ext.decode(response.responseText); Ext.MessageBox.alert(i18n('page.module.oneToMany.message'),json.message); } }); } }); } else { Ext.Msg.alert(i18n('page.module.oneToMany.message'), i18n('page.module.oneToMany.priceAreaGrid.message')); } } } ], bbar : Ext.create('Ext.toolbar.Paging', { id : 'priceAreaGrid_pagingToolbar', store : priceAreaStore, displayMsg : i18n('page.module.oneToMany.priceAreaGrid.displayMsg'), displayInfo : true, items:[ '-',{ text: i18n('page.module.oneToMany.priceAreaGrid.page_count'), xtype: 'tbtext' },Ext.create('Ext.form.ComboBox', { width: 50, value: '20', triggerAction: 'all', forceSelection: true, editable: false, name: 'comboItem', displayField: 'value', valueField: 'value', queryMode: 'local', store : Ext.create('Ext.data.Store',{ fields : ['value'], data : [ {'value':'10'}, {'value':'15'}, {'value':'20'}, {'value':'25'}, {'value':'40'}, {'value':'100'} ] }), listeners:{ select : {scope : this, fn: function(_field,_value){ var pageSize = priceAreaStore.pageSize; var newPageSize = parseInt(_field.value); if(pageSize!=newPageSize){ priceAreaStore.pageSize = newPageSize; Ext.getCmp('priceAreaGrid_pagingToolbar').moveFirst(); } } } } }),{ text: i18n('page.module.oneToMany.priceAreaGrid.number'), xtype: 'tbtext' }] })}); Ext.onReady(function() { setTimeout(function() { Ext.get('loading').remove(); Ext.get('loading-mask').fadeOut({ remove : true }); }, 1000); Ext.QuickTips.init(); Ext.form.Field.prototype.msgTarget = "side"; Ext.create('Ext.Viewport',{ layout : { type : 'border' }, defaults : { split : true }, width : window.screen.availWidth, height : window.screen.availHeight, items : [{ xtype : 'form', id : "chack_form", region : 'north', border : false, hight : 50, width : 500, layout : { type : 'hbox', padding : 5 }, baseCls : 'x-plain', items : [{ xtype : 'textfield', fieldLabel : i18n('page.module.oneToMany.areaCode'), labelPad : 2, labelWidth : 80, name : 'priceArea.areaCode', width : 250, hight : 25 },{ xtype : 'label', width : 50 },{ xtype : 'textfield', fieldLabel : i18n('page.module.oneToMany.areaName'), labelPad : 2, labelWidth : 80, name : 'priceArea.areaName', width : 250, hight : 25 },{ xtype : 'label', width : 50 },{ xtype : 'button', text : i18n('page.module.oneToMany.button_chick'), width : 100, hight : 25, handler : function() { priceAreaStore.load({ params : { 'priceArea.areaName' : this.up('form').getForm().findField("priceArea.areaName").getValue(), 'priceArea.areaCode' : this.up('form').getForm().findField("priceArea.areaCode").getValue() } }); } } ] }, { region : 'center', border:false, autoScroll : true, items : [ priceAreaGrid ] }] });});


        打开的过程是:

        1. 点击新增(执行“createWin(new priceAreaModel());”,这里为什么要新建一个priceAreaModel,是为了让后面与form绑定的时候有一个对象)
        2. 得到价格区域编辑页面(根据传入的priceAreaModel对象绑定表单,执行priceForm.loadRecord(record);)

        保存的过程是:

        1. 得到表单的绑定对象“new_record = form.getRecord();”;
        2. 在把表单的更新信息写入绑定对象“form.updateRecord(new_record);”);
        3. 新建设一个orderBillAction 对象var priceAreaAction = new PriceAreaAction();接下来要注意的下面这一点:priceAreaAction.phantom = new_record.phantom

        一定要把得到的表单绑定信息的phantom这个属性值给action对象,这样才可以完成action对象的save方法的请求选择,如果phantom是true,那么就是执行“create”,否则就就执行“update”。

        绑定对象中绑定的信息只能是表单中的信息,不能是表格中的信息,也就是priceAreaModel对象只能更新得到表单中的信息,不能得到表格中的订单明细信息,而且提交的信息是直接注入到Action中,所以要对订单明细信息做特别的处理。就是执行“processAction (_action,_record,_store)”方法,把增删改的订单明细信息加入到PriceAreaAction对象中,还有订单信息也注入到对象中。

          /** * 用于处理提交数据 * * @param _action * @param _record * @param _store * @returns */function processAction(_action, _record, _store) { var _create = new Array(); var _update = new Array(); var _delete = new Array(); var removed = _store.getRemovedRecords(); var updated = _store.getUpdatedRecords(); var newed = _store.getNewRecords(); Ext.each(removed, function(record) { _delete.push(record.data); }); Ext.each(updated, function(record) { _update.push(record.data); }); Ext.each(newed, function(record) { _create.push(record.data); }); _action.set('updatePriceEntrys', _update); _action.set('createPriceEntrys', _create); _action.set('deletePriceEntrys', _delete); _action.set('priceArea', _record.data); return _action;}

          所以在PriceAreaAction这个model要定义增删改的区域价格明细信息属性与区域属性“'priceArea', 'updatePriceEntrys',

          'createPriceEntrys','deletePriceEntrys'”,在方法中就要把增删改的信息分别set到PriceAreaAction对象中。

          在model中定义一个proxy,信息如下:

            proxy : { type : 'ajax', api : { create : 'savePriceArea.action', update : 'updatePriceArea.action' }, writer : { type : 'json' }, reader : { type : 'json' } }

            用PriceAreaAction对象的save方法,就会发一个create对应的URL(savePriceArea.action),用定义的writer把区域价格信息以JSON的格式写回到服务端。

            修改过程说明:

            1. 双击表格中的行(执行“createWin(record);”,得到订单修改页面,根据传入的record对象绑定表单,执行“priceForm.loadRecord(record);”进行绑定);
            2. 进行表单信息与表格信息的修改;
            3. 点击保存,得到表单的绑定对象“new_record = form.getRecord();”;
            4. 在把表单的更新信息写入绑定对象“form.updateRecord(new_record);”);
            5. 接下来的过程与新增的一样。

            在开发过程中可以要对日期进行处理,对日期做处理可以有如下正反向两种方式:

              /** * 修改date对象数据的JSON提交方式 */Ext.JSON.encodeDate = function(d) { return d.getTime();};/** * 处理日期展现方式 * @param value * @returns */function changeToDate(value) { if (value != null) { var date = new Date(value); return Ext.Date.format(date, 'Y-m-d H:i:s'); } else { return null; }};

读书人网 >JavaScript

热点推荐