grid中数据的保存,添加和删除

本文转载自http://www.cnblogs.com/yage/archive/2009/10/30/1591785.html

在上一个系列当中,我们学习了如何对grid中的内容进行编辑,但是编辑的结果我们并没有保存,这在实际的应用中是没有什么意义的。在有些情况下,除了编辑之外,还要通过grid进行数据的增加和删除,这两个操作也涉及到对于数据的保存。在这个系列里边,我们将学习如何保存数据以及通过grid对数据进行增加和删除。

    我们在前边的学习过程中已经知道,grid其实只是显示数据,它通过配置参数store来获得数据,这个参数需要的是Store类或者其子类的一个对象,里边封装了我们需要的数据。我们现在应该已经比较熟悉Store类了,这次我们需要使用它的一个属性modified,里边保存了被修改过的记录的集合。我们通过把上个系列中的例子改变一下来看看如何保存数据:

[javascript] view plain copy
  1. ///<reference path="vswd-ext_2.0.2.js" />  
  2. /**//* 
  3. *作者:大笨 
  4. *日期:2009-10-20 
  5. *版本:1.0 
  6. *博客地址:http://yage.cnblogs.com 
  7. *QQ:14202190 
  8. */  
  9. Ext.BLANK_IMAGE_URL = '../extjs/resources/images/default/s.gif';  
  10.   
  11. Ext.onReady(function() {  
  12.     Ext.QuickTips.init();  
  13.   
  14.     //格式化日期  
  15.     function formatDate(value) {  
  16.         return value ? value.dateFormat('Y年m月d日') : '';  
  17.     }  
  18.   
  19.     // 别名  
  20.     var fm = Ext.form;  
  21.   
  22.     //构造一个只能包含checkbox的列  
  23.     var checkColumn = new Ext.grid.CheckColumn({  
  24.         header: 'Indoor?',  
  25.         dataIndex: 'indoor',  
  26.         width: 55  
  27.     });  
  28.   
  29.     // 构造ColumnModel  
  30.     var cm = new Ext.grid.ColumnModel({  
  31.         columns: [{  
  32.             id: 'common',  
  33.             header: 'Common Name',  
  34.             dataIndex: 'common',  
  35.             width: 220,  
  36.             // 使用上边定义好的别名  
  37.             editor: new fm.TextField({  
  38.                 allowBlank: false  
  39.             })  
  40.         }, {  
  41.             header: 'Light',  
  42.             dataIndex: 'light',  
  43.             width: 130,  
  44.             editor: new fm.ComboBox({  
  45.                 typeAhead: true,  
  46.                 triggerAction: 'all',  
  47.                 transform: 'light',  
  48.                 lazyRender: true,  
  49.                 listClass: 'x-combo-list-small'  
  50.             })  
  51.         }, {  
  52.             header: 'Price',  
  53.             dataIndex: 'price',  
  54.             width: 70,  
  55.             align: 'right',  
  56.             renderer: 'usMoney',  
  57.             editor: new fm.NumberField({  
  58.                 allowBlank: false,  
  59.                 allowNegative: false,  
  60.                 maxValue: 100000  
  61.             })  
  62.         }, {  
  63.             header: 'Available',  
  64.             dataIndex: 'availDate',  
  65.             width: 95,  
  66.             renderer: formatDate,  
  67.             editor: new fm.DateField({  
  68.                 format: 'Y年m月d日',  
  69.                 minValue: '01/01/06',  
  70.                 disabledDays: [0, 6],  
  71.                 disabledDaysText: 'Plants are not available on the weekends'  
  72.             })  
  73.         },  
  74.         checkColumn  
  75.     ],  
  76.         defaults: {  
  77.             sortable: true  
  78.         }  
  79.     });  
  80.   
  81.   
  82.     // 构造一个Store对象  
  83.     var store = new Ext.data.Store({  
  84.   
  85.         url: 'plants.xml',  
  86.   
  87.         reader: new Ext.data.XmlReader(  
  88.             {  
  89.                 record: 'plant'  
  90.             },  
  91.   
  92.             [  
  93.                 { name: 'common', type: 'string' },  
  94.                 { name: 'botanical', type: 'string' },  
  95.                 { name: 'light' },  
  96.                 { name: 'price', type: 'float' },  
  97.                 { name: 'availDate', mapping: 'availability', type: 'date', dateFormat: 'm/d/Y' },  
  98.                 { name: 'indoor', type: 'bool' }  
  99.             ]  
  100.         ),  
  101.   
  102.         sortInfo: { field: 'common', direction: 'ASC' }  
  103.     });  
  104.   
  105.     // 构造可编辑的grid  
  106.     var grid = new Ext.grid.EditorGridPanel({  
  107.         store: store,  
  108.         cm: cm,  
  109.         renderTo: 'grid',  
  110.         width: 600,  
  111.         height: 300,  
  112.         autoExpandColumn: 'common',  
  113.         title: 'Edit Plants?',  
  114.         frame: true,  
  115.         plugins: checkColumn,  
  116.         clicksToEdit: 1,  
  117.         listeners: {  
  118.             "afterEdit": {  
  119.                 fn: afterEdit,  
  120.                 scope: this  
  121.             }  
  122.         },  
  123.         tbar: [{  
  124.             text: "保存",  
  125.             handler: function() {  
  126.                 var modified = store.modified;  
  127.                 updateData(modified);  
  128.             }  
  129.         }]  
  130.     });  
  131.   
  132.     // 触发数据的加载  
  133.     store.load();  
  134.   
  135.     //发送数据到服务器端进行更新  
  136.     function updateData(modified) {  
  137.         var json = [];  
  138.         Ext.each(modified, function(item) {  
  139.             json.push(item.data);  
  140.         });  
  141.         if (json.length > 0) {  
  142.             Ext.Ajax.request({  
  143.                 url: "EditGrid.aspx",  
  144.                 params: { data: Ext.util.JSON.encode(json) },  
  145.                 method: "POST",  
  146.                 success: function(response) {  
  147.                     Ext.Msg.alert("信息""数据更新成功!"function() { store.reload(); });  
  148.                 },  
  149.                 failure: function(response) {  
  150.                     Ext.Msg.alert("警告""数据更新失败,请稍后再试!");  
  151.                 }  
  152.             });  
  153.         }  
  154.         else {  
  155.             Ext.Msg.alert("警告""没有任何需要更新的数据!");  
  156.         }  
  157.     }  
  158.   
  159.     //编辑后触发的事件,可在此进行数据有效性的验证  
  160.     function afterEdit(e) {  
  161.         if (e.field == "common") {  
  162.             if (e.value == "大笨") {  
  163.                 Ext.Msg.alert("错误""大笨是人物不是植物"function() { grid.startEditing(e.row, e.column) });  
  164.             }  
  165.         }  
  166.     }  
  167. });  

我们首先给grid增加了一个afterEdit事件,顾名思义,该事件在编辑之后被触发,我们可以在此时对数据的有效性进行验证,在本例中,我们只是简单的让common列的值不能等于一个特定的字符串,实际的项目中可能需要对每一列用正则表达式来进行验证。在触发afterEdit事件的时候会传递一个事件对象,该对象有如下几个属性:
    grid:当前grid。
    record:当前行。
    field:当前列名。
    value:被设置的值。
    originalValue:编辑前的值。
     row:行索引。
    column:列索引。

     我们还在grid上加了一个工具栏,上边放了一个保存按钮,用以将修改后的数据传递到服务器进行保存。由于记录的集合是一个复杂的json对象,我们需要的只是相关数据的几个,因此第137-140行对该集合进行了处理。当然,我们还需要在服务器端接收数据然后进行处理,在系列一中我们已经学习到相关的方法,这里不再赘述。我们看一看运行之后的效果图:

通过firebug,我们可以看到向服务器投递的数据:

接下来看看如何添加数据,我们在工具栏里边添加一个增加按钮,相关代码如下:

[javascript] view plain copy
  1. tbar: [{  
  2.             text: "保存",  
  3.             handler: function() {  
  4.                 var modified = store.modified;  
  5.   
  6.                 updateData(modified);  
  7.             }  
  8.         },  
  9.             '-',  
  10.             {  
  11.                 text: "增加",  
  12.                 handler: function() {  
  13.                     var Plant = store.recordType;  
  14.                     var p = new Plant({  
  15.                         common: 'New Plant 1',  
  16.                         light: 'Mostly Shade',  
  17.                         price: 0,  
  18.                         availDate: (new Date()).clearTime(),  
  19.                         indoor: false  
  20.                     });  
  21.                     grid.stopEditing();  
  22.                     store.insert(0, p);  
  23.                     grid.startEditing(0, 0);  
  24.                 }  
  25.             }  
  26.                 ]  

在向grid中插入数据之前,必须要先获得插入数据的格式,Store类的recordType属性返回Record的构造函数,表明了数据的格式,然后通过构造函数传递数据,这样就准备好了要插入的数据了。接下来将grid的编辑状态关闭,插入数据,然后把要插入数据的第一列设置为编辑状态。运行后点击增加按钮后的效果如下:

 

可以看到,在grid的最上边增加了一行,对应行索引0,第一列出于编辑状态,对应列索引1,增加行中的默认初始数据就是我们在构造函数中传递进来的数据。注意,新增加的数据在修改之前是不会保存在store的modified属性里边的。

    我们再来看看如何进行删除操作。在进行删除之前,我们必须要选择需要删除的行,grid有单元格选择模型和行选择模型两种,分别以类CellSelectionModel和RowSelectionModel来表示,默认是单元格选择模型,也就是在点击单元格的时候选中的是当前单元格,可以通过配置属性selModle(可简写为sm)来指定选择模式:sm:new Ext.grid.RowSelectionModel({singleSelection:true}), 这样就把选择模型改为了行选择模型,参数singleSelect指明是否是单选的,为真的时候只能选择一行,默认是false,可以按下ctrl键或者shift键进行多行的选择。选择好之后,我们就来看看如何删除吧:

可以看到,在grid的最上边增加了一行,对应行索引0,第一列出于编辑状态,对应列索引1,增加行中的默认初始数据就是我们在构造函数中传递进来的数据。注意,新增加的数据在修改之前是不会保存在store的modified属性里边的。

    我们再来看看如何进行删除操作。在进行删除之前,我们必须要选择需要删除的行,grid有单元格选择模型和行选择模型两种,分别以类CellSelectionModel和RowSelectionModel来表示,默认是单元格选择模型,也就是在点击单元格的时候选中的是当前单元格,可以通过配置属性selModle(可简写为sm)来指定选择模式:sm:new Ext.grid.RowSelectionModel({singleSelection:true}), 这样就把选择模型改为了行选择模型,参数singleSelect指明是否是单选的,为真的时候只能选择一行,默认是false,可以按下ctrl键或者shift键进行多行的选择。选择好之后,我们就来看看如何删除吧:

[javascript] view plain copy
  1. tbar: [{  
  2.             text: "保存",  
  3.             handler: function() {  
  4.                 var modified = store.modified;  
  5.                 updateData(modified);  
  6.             }  
  7.         },  
  8.             '-',  
  9.             {  
  10.                 text: "增加",  
  11.                 handler: function() {  
  12.                     var Plant = store.recordType;  
  13.                     var p = new Plant({  
  14.                         common: 'New Plant 1',  
  15.                         light: 'Mostly Shade',  
  16.                         price: 0,  
  17.                         availDate: (new Date()).clearTime(),  
  18.                         indoor: false  
  19.                     });  
  20.                     grid.stopEditing();  
  21.                     store.insert(0, p);  
  22.                     grid.startEditing(0, 0);  
  23.                 }  
  24.             },  
  25.             " ",  
  26.             {  
  27.                 text: "删除",  
  28.                 handler: function() {  
  29.                     var selModel = grid.getSelectionModel();  
  30.                     if (selModel.hasSelection()) {  
  31.                         Ext.Msg.confirm("警告""确定要删除吗?"function(button) {  
  32.                             if (button == "yes") {  
  33.                                 var selections = selModel.getSelections();  
  34.                                 Ext.each(selections, function(item) {  
  35.                                     store.remove(item);  
  36.                                 });  
  37.                             }  
  38.                         });  
  39.                     }  
  40.                     else {  
  41.                         Ext.Msg.alert("错误""没有任何行被选中,无法进行删除操作!");  
  42.                     }  
  43.                 }  
  44.             }  
  45.                 ]  
  

我们先通过grid的getSelectionModel方法获得当前的选择模型,由于当前我们使用了行选择模型,所以返回的是RowSelectionModel的对象,然后通过该对象的hasSelection方法判断有没有行呗选中,没有的话就弹出一个对话框,如果有选中的行要被删除,弹出一个提示框让用户确定删除操作,如果确实要删除,使用RowSelectionModel对象的getSelections方法返回所有被选择行的集合,遍历此集合,从store中去掉集合中的行。看看效果图:

点击“是”,所有选中的行被删除,通过firebug可以看到被删除的行在store的removed属性中保存。

    但是有些人可能不习惯这里所谓的行选择模型,他们可能喜欢看到在每一行的前边有一个checkbox,勾选了之后表示选择该行,extjs中的CheckboxSelectionModel类可以方便的让我们实现这一点,该类继承自RowSelectionModel,说明这只是一种特殊的行选择模型。我们具体来看看怎么进行操作。首先需要定义一个CheckboxSelectionModel的对象:var sm=new Ext.grid.CheckboxSelctionModle({checkOnly:true}),这里chckOnly:true表明只能通过checkbox来选择行,为false的话则还可以通过我们上边提到的方法来选择行。接下来需要把原来的行选择模型替换成我们新的sm,然后运行一下看看吧。我们没有看到预期中的效果,这是为什么呢?仔细想一想,确实应该是看不到什么效果,我们知道列都是在ColumnModel里边配置的,我们的CheckboxSelectionModel需要添加一列,自然也要在其中配置。那我们就加上去吧,完整的代码如下:

[javascript] view plain copy
  1. ///<reference path="vswd-ext_2.0.2.js" />  
  2. /* 
  3. *作者:大笨 
  4. *日期:2009-10-20 
  5. *版本:1.0 
  6. *博客地址:http://yage.cnblogs.com 
  7. *QQ:14202190 
  8. */  
  9. Ext.BLANK_IMAGE_URL = '../extjs/resources/images/default/s.gif';  
  10.   
  11. Ext.onReady(function() {  
  12.     Ext.QuickTips.init();  
  13.   
  14.     //格式化日期  
  15.     function formatDate(value) {  
  16.         return value ? value.dateFormat('Y年m月d日') : '';  
  17.     }  
  18.   
  19.     // 别名  
  20.     var fm = Ext.form;  
  21.   
  22.     //checkbox选择模型  
  23.     var sm = new Ext.grid.CheckboxSelectionModel({ checkOnly: true });  
  24.       
  25.     //构造一个只能包含checkbox的列  
  26.     var checkColumn = new Ext.grid.CheckColumn({  
  27.         header: 'Indoor?',  
  28.         dataIndex: 'indoor',  
  29.         width: 55  
  30.     });  
  31.   
  32.     // 构造ColumnModel  
  33.     var cm = new Ext.grid.ColumnModel({  
  34.     columns: [  
  35.         sm,  
  36.         {  
  37.             id: 'common',  
  38.             header: 'Common Name',  
  39.             dataIndex: 'common',  
  40.             width: 220,  
  41.             // 使用上边定义好的别名  
  42.             editor: new fm.TextField({  
  43.                 allowBlank: false  
  44.             })  
  45.         }, {  
  46.             header: 'Light',  
  47.             dataIndex: 'light',  
  48.             width: 130,  
  49.             editor: new fm.ComboBox({  
  50.                 typeAhead: true,  
  51.                 triggerAction: 'all',  
  52.                 transform: 'light',  
  53.                 lazyRender: true,  
  54.                 listClass: 'x-combo-list-small'  
  55.             })  
  56.         }, {  
  57.             header: 'Price',  
  58.             dataIndex: 'price',  
  59.             width: 70,  
  60.             align: 'right',  
  61.             renderer: 'usMoney',  
  62.             editor: new fm.NumberField({  
  63.                 allowBlank: false,  
  64.                 allowNegative: false,  
  65.                 maxValue: 100000  
  66.             })  
  67.         }, {  
  68.             header: 'Available',  
  69.             dataIndex: 'availDate',  
  70.             width: 95,  
  71.             renderer: formatDate,  
  72.             editor: new fm.DateField({  
  73.                 format: 'Y年m月d日',  
  74.                 minValue: '01/01/06',  
  75.                 disabledDays: [0, 6],  
  76.                 disabledDaysText: 'Plants are not available on the weekends'  
  77.             })  
  78.         },  
  79.         checkColumn,  
  80.     ],  
  81.         defaults: {  
  82.             sortable: true  
  83.         }  
  84.     });  
  85.   
  86.   
  87.     // 构造一个Store对象  
  88.     var store = new Ext.data.Store({  
  89.   
  90.         url: 'plants.xml',  
  91.   
  92.         reader: new Ext.data.XmlReader(  
  93.             {  
  94.                 record: 'plant'  
  95.             },  
  96.   
  97.             [  
  98.                 { name: 'common', type: 'string' },  
  99.                 { name: 'botanical', type: 'string' },  
  100.                 { name: 'light' },  
  101.                 { name: 'price', type: 'float' },  
  102.                 { name: 'availDate', mapping: 'availability', type: 'date', dateFormat: 'm/d/Y' },  
  103.                 { name: 'indoor', type: 'bool' }  
  104.             ]  
  105.         ),  
  106.         sortInfo: { field: 'common', direction: 'ASC' }  
  107.     });  
  108.   
  109.     // 构造可编辑的grid  
  110.     var grid = new Ext.grid.EditorGridPanel({  
  111.         //sm: new Ext.grid.RowSelectionModel({ singleSelect: false }),  
  112.         sm: sm,  
  113.         store: store,  
  114.         cm: cm,  
  115.         renderTo: 'grid',  
  116.         width: 600,  
  117.         height: 300,  
  118.         autoExpandColumn: 'common',  
  119.         title: 'Edit Plants?',  
  120.         frame: true,  
  121.         plugins: checkColumn,  
  122.         clicksToEdit: 2,  
  123.         listeners: {  
  124.             "afterEdit": {  
  125.                 fn: afterEdit,  
  126.                 scope: this  
  127.             }  
  128.         },  
  129.         tbar: [{  
  130.             text: "保存",  
  131.             handler: function() {  
  132.                 var modified = store.modified;  
  133.                 updateData(modified);  
  134.             }  
  135.         },  
  136.             '-',  
  137.             {  
  138.                 text: "增加",  
  139.                 handler: function() {  
  140.                     var Plant = store.recordType;  
  141.                     var p = new Plant({  
  142.                         common: 'New Plant 1',  
  143.                         light: 'Mostly Shade',  
  144.                         price: 0,  
  145.                         availDate: (new Date()).clearTime(),  
  146.                         indoor: false  
  147.                     });  
  148.                     grid.stopEditing();  
  149.                     store.insert(0, p);  
  150.                     grid.startEditing(0, 0);  
  151.                 }  
  152.             },  
  153.             " ",  
  154.             {  
  155.                 text: "删除",  
  156.                 handler: function() {  
  157.                     var selModel = grid.getSelectionModel();  
  158.                     if (selModel.hasSelection()) {  
  159.                         Ext.Msg.confirm("警告""确定要删除吗?"function(button) {  
  160.                             if (button == "yes") {  
  161.                                 var selections = selModel.getSelections();  
  162.                                 Ext.each(selections, function(item) {  
  163.                                     store.remove(item);  
  164.                                     store.removed.push(item);  
  165.                                 });  
  166.                             }  
  167.   
  168.                         });  
  169.                     }  
  170.                     else {  
  171.                         Ext.Msg.alert("错误""没有任何行被选中,无法进行删除操作!");  
  172.                     }  
  173.                 }  
  174.             }  
  175.                 ]  
  176.     });  
  177.   
  178.     // 触发数据的加载  
  179.     store.load();  
  180.   
  181.     //发送数据到服务器端进行更新  
  182.     function updateData(modified) {  
  183.         var json = [];  
  184.         Ext.each(modified, function(item) {  
  185.             json.push(item.data);  
  186.         });  
  187.         if (json.length > 0) {  
  188.             Ext.Ajax.request({  
  189.                 url: "EditGrid.aspx",  
  190.                 params: { data: Ext.util.JSON.encode(json) },  
  191.                 method: "POST",  
  192.                 success: function(response) {  
  193.                     Ext.Msg.alert("信息""数据更新成功!"function() { store.reload(); });  
  194.                 },  
  195.                 failure: function(response) {  
  196.                     Ext.Msg.alert("警告""数据更新失败,请稍后再试!");  
  197.                 }  
  198.             });  
  199.         }  
  200.         else {  
  201.             Ext.Msg.alert("警告""没有任何需要更新的数据!");  
  202.         }  
  203.     }  
  204.   
  205.     //编辑后触发的事件,可在此进行数据有效性的验证  
  206.     function afterEdit(e) {  
  207.         if (e.field == "common") {  
  208.             if (e.value == "大笨") {  
  209.                 Ext.Msg.alert("错误""大笨是人物不是植物"function() { grid.startEditing(e.row, e.column) });  
  210.             }  
  211.         }  
  212.     }  
  213. });  

 再运行一下看看,OK,我们想要的效果出来了:

最后我们来总结一下,当修改grid中的内容时,Store类的modified会自动将被修改的行保存下来;当删除的时候,Store类给我们提供了一个 removed属性,但不知道为什么不自动保存删除的行,不过自己添加也很简单;增加是最麻烦的,我们可能需要一些小技巧来保存添加的行,无论是修改的还是未修改的,可以都放到Store类的modified属性之中,也可以放在自己建的一个集合中,但是需要从modified里边去被添加之后修改的行。无论是编辑,增加或者删除操作,都是在本地进行,需要自己写代码将改动发送到服务器端进行处理。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值