EXTJS记事本 当CompositeField遇上RowEditor


Posted in Javascript onJuly 31, 2011

原因是客户的物料种类非常多,有一千种之多,如果单纯用一个Combobox,那么在实际使用中,很难快速找到一个物料,所以,我使用包含物料分类和物料品牌的两个combobox来组成级联式筛选。问题恰恰出在这儿,如果在roweditor的一个字段中用多个控件,就要处理每个控件的初始化,Change事件。网上目前还未找到有人有好的解决办法。经过3天的调试,我终于解决了问题,把我的代码贴出来:

var editor=new Ext.ux.grid.RowEditor({ 
saveText: '确定', 
cancelText:"放弃", 
commitChangesText: '请确定或放弃修改', 
errorText: '错误' 
}); 
//当取消时,根据关键字段的值是否为空而删掉空记录 
editor.on("canceledit",function(editor,pressed) 
{ 
if(pressed && editor.record.get("materialid")==0) 
{ 
store.remove(editor.record); 
} 
},this); 
/* 
afterstart 这个事件是自己加的,因为如果在beforeedit事件中想对自己的控件初始化,那是不可能的,因为beforeedit时,roweditor控件还没有渲染,所以,我加了afterstart事件,该事件在roweditor显示后立即调用,所以,可以在这里进行初始化。 
要注意的是通过roweditor控件进行遍历来访问自定义的composite控件 
editor.items.items[0],这里并不是我写重了,而是roweditor控件的items竟然不是一个集合,而是一个对象,在这里我也耗了一些时间,最后还是通过firebug输出editor对象发现的 
editor.items.items[0]就是compositefield组件,通过该组件的items集合,就可以以标准的形式访问其子组件,接下来,就可以初始化了 
因为最后一个combobox的数据是要通过前两个combobox级联选取后载入的,所以,在这里载入其数据进行初始化,但是注意,我是在callback中执行的,因为jsonstore的load动作是异步的,所以,必须通过callback事件的回调在数据载入成功后,再用setValue来初始化值 
*/ 
editor.on("afterstart",function(editor,rowIndex) 
{ 
var record=store.getAt(rowIndex); 
editor.items.items[0].items.items[0].setValue(record.get("setid")); 
editor.items.items[0].items.items[1].setValue(record.get("category")); 
var t_store=editor.items.items[0].items.items[2].getStore(); 
t_store.load({ 
params:{category:record.get("category"),setid:record.get("setid")}, 
callback:function(r,options,success){ 
if (success) 
editor.items.items[0].items.items[2].setValue(record.get("materialid")); 
} 
}); 
},this); 
/* 
validateedit事件是在按了确认时执行的,用来验证roweditor中各控件的值,在这里,我执行了一个自定义的验证动作,因为我不想用户可以添加重复的物料,所以,我通过遍历jsonstore,将每条记录的物料值与用户选择的物料值进行比较,如果发现已经存在,则提示用户不要重复加入 
*/ 
editor.on("validateedit",function(editor,obj,record,rowIndex){ 
var materialid=editor.items.items[0].items.items[2].getValue(); 
var exist=false; 
Ext.each(store.getRange(),function(o,i){ 
if(o!=record&&o.get("materialid")==materialid) 
{ 
exist=true; 
return(false); 
} 
}); 
if(exist) 
{ 
Ext.MessageBox.alert("系统提示","请勿重复添加"); 
store.remove(record); 
} 
return(!exist); 
},this); 
/* 
afterEdit是通过验证后执行的,这里最重要的动作是将正在编辑的记录的某些属性赋值,原因是由于采用了compsitefield,所以,roweditor无法将选取的值赋给record的正确属性,需要我们手工将用户的选择赋给相应的字段,materialid就是用户选的物料编号,而model对应是该物料的型号 
为什么要赋model呢?因为model是列的值嘛,不赋的话,显示的是空的 
*/ 
editor.on("afteredit",function(editor,obj,record,rowIndex){ 
record.set("materialid",editor.items.items[0].items.items[2].getValue()); 
record.set("model",editor.items.items[0].items.items[2].getRawValue()); 
},this);

以上是roweditor的定义和对事件的处理,接下来,将roweditor作为插件插入到gridpanel
{ 
xtype:"grid", 
title:"产品BOM", 
layout:"fit", 
store:store, 
enableDragDrop: false, 
border: false, 
frame:false, 
autoScroll:true ,plugins:[editor], 
sm:sm, 
height:340, 
clicksToEdit:2, 
autoWidth: true, 
viewConfig:{forceFit:true,autoFill:true,markDirty:false} 
}

接下来,再看看关于gridpanel的列定义,这里,你可以看到composite是如何用的
columns: [{ header: "物料名称/型号", 
dataIndex: "model", 
width: 200, 
menuDisabled: true, 
editor: 
{ 
//定义编辑器 
xtype:"compositefield", 
name:"compositefield", 
items:[ 
{ 
xtype: "combo", 
mode:"local", 
name:"sets", 
width:80, 
fieldLabel: "适用产品品牌", 
emptyText:"请选择", 
valueField: "id", 
lazyInit:false, 
value:this.data?this.data.title:"", 
hiddenName:"setid", 
hiddenValue:this.data?this.data.setid:"", 
displayField: "title", 
typeAhead: false, 
forceSelection: true, 
editable:true, 
listeners:{ 
"change":function(combo,newvalue,oldvalue) 
{ 
//处理品牌的change事件,在选取品牌后,重新载入combobox,editor就是前文定义的roweditor的实例 
var category=editor.items.items[0].items.items[1]; 
var material=editor.items.items[0].items.items[2]; 
var c=category.getValue(); 
var store=material.getStore(); 
store.load({ 
params:{setid:newvalue,category:c}, 
callback:function(r,options,success){ 
if (success) 
material.setValue(""); 
} 
}); 
} 
}, 
triggerAction: "all", 
store: new Ext.data.JsonStore({ 
url: "<%=script_path%>data.asp", 
root: "data",autoDestroy:true, 
remoteSort: true, 
listeners:{"load":function(store,records,option){ 
var s=Ext.data.Record.create([{name:"id",type:"int"},{name:"title",type:"string"}]); 
store.add(new s({id:0,title:"通用"})) 
}}, 
baseParams: {op: "setList"}, 
totalProperty: "total", 
autoLoad: true, 
fields: ["title","id"] 
}) 
}, 
{ 
xtype: "combo", 
mode:"local",width:60, 
name:"category", 
fieldLabel: "类别", 
emptyText:"请选择", 
valueField: "category", 
lazyInit:false, 
value:this.data?this.data.category:"", 
displayField: "category", 
typeAhead: false,forceSelection: true, 
triggerAction: "all", 
listeners:{ 
"change":function(combo,newvalue,oldvalue) 
{ 
//处理类别的change事件,在选取品牌后,重新载入combobox,editor就是前文定义的roweditor的实例 
var sets=editor.items.items[0].items.items[0]; 
var material=editor.items.items[0].items.items[2]; 
var setid=sets.getValue(); 
var store=material.getStore(); 
store.load({ 
params:{category:newvalue,setid:setid}, 
callback:function(r,options,success){ 
if (success) 
material.setValue(""); 
} 
}); 
} 
}, 
store: new Ext.data.JsonStore({ 
url: "<%=script_path%>data.asp", 
root: "data",autoDestroy:true, 
remoteSort: true, 
baseParams: {op: "materialCategoryList"}, 
totalProperty: "total", 
autoLoad: true, 
fields: ["category"] 
}) 

}, 
{ 
xtype: "combo", 
forceSelection: true, 
editable:true, 
mode:"local", 
name:"material", 
fieldLabel: "物料", 
emptyText:"请选择物料", 
valueField: "id", 
allowBlank:false, 
displayField: "model", 
width:250, 
lazyInit:false, 
typeAhead: false, 
triggerAction: "all", 
listeners:{ 
"change":function(combo,newvalue,oldvalue) 
{ 
//这里一定要注意!!!如果没有下面这两句,那你选择后,会发现显示的值不会变化,并且,点了确认,也不能更新。为什么呢?因为roweditor是通过检测record的isdirty属性来决定是不是调用validateedito和afteredit的,它是检测每列对应的控件值是否变化来判断的,由于物料型号这列,对应的是compositefield,所以,我们必须让compositefield值发生变化,roweditor才会调用validedit和afteredit,并且,compositefield的值还会被调用来显示在列里 
var comp=editor.items.items[0]; 
comp.setRawValue(combo.getRawValue()); 
} 
}, 
store: new Ext.data.JsonStore({ 
url: "<%=script_path%>data.asp", 
root: "data",autoDestroy:true, 
remoteSort: true, 
baseParams: {op: "materialList"}, 
totalProperty: "total", 
autoLoad: false, 
fields: ["model","id"] 
})} 
] 
} 

}, 
{ 
header: "数量", 
dataIndex: "qty", 
width: 50, 
menuDisabled: true, 
editor: { 
xtype: 'numberfield', 
minValue:1, 
allowDecimals:false 
} 
} 
,{ 
header: "颜色", 
dataIndex: "color", 
width: 60, 
menuDisabled: true 
} 
,{ 
header: "尺寸", 
dataIndex: "size", 
width: 60, 
menuDisabled: true 
} 
] 

} 

]

谨以此记,分享给有需要的朋友
Javascript 相关文章推荐
jQuery随便控制任意div隐藏的方法
Jun 28 Javascript
js模仿hover的具体实现代码
Dec 30 Javascript
js查找节点的方法小结
Jan 13 Javascript
分享五个有用的jquery小技巧
Oct 08 Javascript
大型JavaScript应用程序架构设计模式
Jun 29 Javascript
BootStrap Table 获取同行不同列元素的方法
Dec 19 Javascript
js实现选项卡内容切换以及折叠和展开效果【推荐】
Jan 08 Javascript
微信小程序picker组件下拉框选择input输入框的实例
Sep 20 Javascript
详解vscode中vue代码颜色插件
Oct 11 Javascript
JavaScript使用canvas绘制随机验证码
Feb 17 Javascript
如何构建 vue-ssr 项目的方法步骤
Aug 04 Javascript
Javascript 类、命名空间、代码组织代码
Jul 31 #Javascript
仅img元素创建后不添加到文档中会执行onload事件的解决方法
Jul 31 #Javascript
IE6/7 and IE8/9/10(IE7模式)依次隐藏具有absolute或relative的父元素和子元素后再显示父元素
Jul 31 #Javascript
读jQuery之十二 删除事件核心方法
Jul 31 #Javascript
读jQuery之十一 添加事件核心方法
Jul 31 #Javascript
仅Firefox中链接A无法实现模拟点击以触发其默认行为
Jul 31 #Javascript
各浏览器对click方法的支持差异小结
Jul 31 #Javascript
You might like
PHP 获取MSN好友列表的代码(2009-05-14测试通过)
2009/09/09 PHP
php数组函数序列之array_pop() - 删除数组中的最后一个元素
2011/11/07 PHP
phalcon框架使用指南
2016/02/23 PHP
javascript demo 基本技巧
2009/12/18 Javascript
jQuery 性能优化手册 推荐
2010/02/23 Javascript
js遍历td tr等html元素
2012/12/13 Javascript
关于jQuery参考实例2.0 用jQuery选择元素
2013/04/07 Javascript
动态加载JS文件的三种方法
2013/11/08 Javascript
javascript的parseFloat()方法精度问题探讨
2013/11/26 Javascript
javascript常见操作汇总
2014/09/03 Javascript
javascript实现动态模态绑定grid过程代码
2014/09/22 Javascript
node.js中的querystring.escape方法使用说明
2014/12/10 Javascript
基于JQuery制作可编辑的表格特效
2014/12/23 Javascript
解析ajaxFileUpload 异步上传文件简单使用
2016/12/30 Javascript
JavaScript解决浮点数计算不准确问题的方法分析
2018/07/09 Javascript
vue中的ref和$refs的使用
2018/11/22 Javascript
ES6 Symbol数据类型的应用实例分析
2019/06/26 Javascript
前端开发之便利店收银系统代码
2019/12/27 Javascript
Vue封装Axios请求和拦截器的步骤
2020/09/16 Javascript
在Django框架中运行Python应用全攻略
2015/07/17 Python
Python抓取聚划算商品分析页面获取商品信息并以XML格式保存到本地
2018/02/23 Python
tensorflow实现图像的裁剪和填充方法
2018/07/27 Python
Python实现iOS自动化打包详解步骤
2018/10/03 Python
Python3爬虫教程之利用Python实现发送天气预报邮件
2018/12/16 Python
Python基于datetime或time模块分别获取当前时间戳的方法实例
2019/02/19 Python
关于Python形参打包与解包小技巧分享
2019/08/24 Python
Python matplotlib生成图片背景透明的示例代码
2019/08/30 Python
解决pycharm导入numpy包的和使用时报错:RuntimeError: The current Numpy installation (‘D:\\python3.6\\lib\\site-packa的问题
2020/12/08 Python
出国考察邀请函
2014/01/21 职场文书
《口技》教学反思
2014/02/21 职场文书
冬季安全检查方案
2014/05/23 职场文书
英语系毕业生求职信
2014/07/13 职场文书
2014年林业工作总结
2014/12/05 职场文书
辞职信模板(中英文版)
2015/02/27 职场文书
2015年计算机教师工作总结
2015/07/22 职场文书
关于践行三严三实的心得体会
2016/01/05 职场文书