上次发了Easyui Datagrid的增删改查的使用学习记录后一直想整理下基于Extjs4.2的Grid学习使用记录。苦于抽不出时间,一直拖到现在。不得不说,Extjs确实很强大,新版的Neptune风格也很入我眼,但毕竟没怎么用过,第一次用,也不敢上来就搞什么自定义组件,也就纯粹的model+store+panel声明式创建表格了。
抛开分页,抛开排序,今天只简单讲一下最近使用中总结出来的rest形式增删改查数据的方式。发现这种方式挺不错的,故而分享下。
代码Example如下:
定义Model
01.Ext.define('Person', {
02. extend: 'Ext.data.Model',
03. fields: [{name: 'id',
04. type: 'int',
05. useNull: true
06. }, 'email', 'first', 'last'],
07. validations: [{ type: 'length',
08. field: 'email',
09. min: 1
10. }, {type: 'length',
11. field: 'first',
12. min: 1
13. }, {type: 'length',
14. field: 'last',
15. min: 1
16. }]
17.});
构造store、创建panel
001.var store = Ext.create('Ext.data.Store', {
002. autoLoad: true,
003. autoSync: true,
004. model: 'Person',
005. proxy: {
006. type: 'ajax',
007. api: {
008. read: 'url/read',//查询
009. create: 'url/create',//创建
010. update: 'url/update',//更新
011. destroy: 'url/destroy'//删除
012. },
013. reader: {
014. type: 'json',
015. root: 'data'
016. },
017. writer: {
018. type: 'json'
019. }
020. },
021. listeners: {
022. write: function(store, operation){
023. var record = operation.getRecords()[0],
024. name = Ext.String.capitalize(operation.action),
025. verb;
026.
027.
028. if (name == 'Destroy') {
029. record = operation.records[0];
030. verb = 'Destroyed';
031. } else {
032. verb = name + 'd';
033. }
034. Ext.example.msg(name, Ext.String.format("{0} user: {1}", verb, record.getId()));
035.
036. }
037. }
038. });
039.
040. var rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
041. listeners: {
042. cancelEdit: function(rowEditing, context) {
043. // Canceling editing of a locally added, unsaved record: remove it
044. if (context.record.phantom) {
045. store.remove(context.record);
046. }
047. }
048. }
049. });
050.
051. var grid = Ext.create('Ext.grid.Panel', {
052. renderTo: document.body,
053. plugins: [rowEditing],
054. width: 400,
055. height: 300,
056. frame: true,
057. title: 'Users',
058. store: store,
059. iconCls: 'icon-user',
060. columns: [{
061. text: 'ID',
062. width: 40,
063. sortable: true,
064. dataIndex: 'id'
065. }, {
066. text: 'Email',
067. flex: 1,
068. sortable: true,
069. dataIndex: 'email',
070. field: {
071. xtype: 'textfield'
072. }
073. }, {
074. header: 'First',
075. width: 80,
076. sortable: true,
077. dataIndex: 'first',
078. field: {
079. xtype: 'textfield'
080. }
081. }, {
082. text: 'Last',
083. width: 80,
084. sortable: true,
085. dataIndex: 'last',
086. field: {
087. xtype: 'textfield'
088. }
089. }],
090. dockedItems: [{
091. xtype: 'toolbar',
092. items: [{
093. text: 'Add',
094. iconCls: 'icon-add',
095. handler: function(){
096. // empty record
097. store.insert(0, new Person());
098. rowEditing.startEdit(0, 0);
099. }
100. }, '-', {
101. itemId: 'delete',
102. text: 'Delete',
103. iconCls: 'icon-delete',
104. disabled: true,
105. handler: function(){
106. var selection = grid.getView().getSelectionModel().getSelection()[0];
107. if (selection) {
108. store.remove(selection);
109. }
110. }
111. }]
112. }]
113. });
114. grid.getSelectionModel().on('selectionchange', function(selModel, selections){
115. grid.down('#delete').setDisabled(selections.length === 0);
很简单,使用api的方式,包括有增删查改,在前台的操作都会被extjs记录下来,再执行sync的时候就可以自动根据状态请求相应的url了。
下面是使用中遇到的一些小问题总结。
1、删除多行数据
例子里使用的是var selection = grid.getView().getSelectionModel().getSelection()[0];注意是加了个[0]的,所以要删除多行,直接取消这个[0],然后执行store即可,前提是你的表格没有限制只能选取一行,默认情况下,cellmodel的mode值为SINGLE,使用checkboxmodel就可以显示checkbox的同时实现多选了。
2、增删查改的同时进行传参
这个一开始同事懒得研究就直接在url里拼上去了,我觉得这样不妥,就查了下相关文章,最终得到两种实现方法
方法一:仅在查询时可用,设置store的autoload为false,手动载入store.load({//to do something});,这样使用查询是可以但是修改删除或者更新时就不好用了。于是有了方法二;
方法二:添加事件监听,在store里面设置linstener,监听beforeload时执行方法,设置Param,如:
1.listeners: {
2. beforeload: function(proxy, response, operation){
3.
4. }
5.}
3、后台动态构造表头不能设置renderer
由于业务特殊性,我们在后台构造json对象包装extjs grid所需的fields、columns,也正因此,不能在后台设置renderer等调用js函数的属性,我的解决方式是,后台添加固定标识,数据到前台后遍历添加所需renderer函数或者特殊编辑器等
后台交互
与后台的交互在一开始还是纠结了半天,没看清楚extjs的实现,原来使用这种方式的请求除了扩展参数以外,表格数据都是通过流交互的。这个在后台是不能直接使用request.getParamter(“xxx”);获取的,因为是使用流,所以需要通过get请求的流来读取数据,又因为是文本数据,所以直接request.getReader().readerLine();获取到的就是json格式的字符串了,接下来就需要自己根据需要进行转换了,个人还是使用json.simple,当然了,具体情况具体对待,如果你的数据有其他的比如文件上传之类的,就需要先获取inputstream再解析了。
就总结这么多了,有任何问题,欢迎留言交流