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 相关文章推荐
JS代码放在head和body中的区别分析
Dec 01 Javascript
js/jquery获取文本框输入焦点的方法
Mar 04 Javascript
javascript随机之洗牌算法深入分析
Jun 07 Javascript
javascript实现瀑布流加载图片原理
Feb 02 Javascript
jQuery 获取屏幕高度、宽度的简单实现案例
May 17 Javascript
手机端点击图片放大特效PhotoSwipe.js插件实现
Aug 24 Javascript
node.js中module.exports与exports用法上的区别
Sep 02 Javascript
微信小程序 picker-view 组件详解及简单实例
Jan 10 Javascript
关于HTTP传输中gzip压缩的秘密探索分析
Jan 12 Javascript
jQuery设置下拉框显示与隐藏效果的方法分析
Sep 15 jQuery
React-redux实现小案例(todolist)的过程
Sep 29 Javascript
vue+springboot实现登录验证码
May 27 Vue.js
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
Destoon模板制作简明教程
2014/06/20 PHP
thinkphp项目部署到Linux服务器上报错“模板不存在”如何解决
2016/04/27 PHP
php英文单词统计器
2016/06/23 PHP
php插件Xajax使用方法详解
2017/08/31 PHP
单独使用CKFinder选择图片的方法
2010/08/21 Javascript
把字符串按照特定的字母顺序进行排序的js代码
2014/01/28 Javascript
ExpressJS入门实例
2015/01/14 Javascript
jquery实现选中单选按钮下拉伸缩效果
2015/08/06 Javascript
javascript实现数组中的内容随机输出
2015/08/11 Javascript
JQuery入门基础小实例(1)
2015/09/17 Javascript
HTML5 Shiv完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法
2015/11/25 Javascript
NodeJS与HTML5相结合实现拖拽多个文件上传到服务器的实现方法
2016/07/26 NodeJs
浅谈js中子页面父页面方法 变量相互调用
2016/08/04 Javascript
Angular.js自动化测试之protractor详解
2017/07/07 Javascript
微信小程序实现人脸识别
2018/05/25 Javascript
Vue项目总结之webpack常规打包优化方案
2019/06/06 Javascript
jQuery操作选中select下拉框的值代码实例
2020/02/07 jQuery
python基础教程之实现石头剪刀布游戏示例
2014/02/11 Python
用实例详解Python中的Django框架中prefetch_related()函数对数据库查询的优化
2015/04/01 Python
Python 私有函数的实例详解
2017/09/11 Python
详解Python基础random模块随机数的生成
2019/03/23 Python
在python image 中安装中文字体的实现方法
2019/08/22 Python
python+django+rest框架配置创建方法
2019/08/31 Python
解决Pycharm 中遇到Unresolved reference 'sklearn'的问题
2020/07/13 Python
基于OpenCV的路面质量检测的实现
2020/11/04 Python
Armor Lux法国官方网站:水手服装、成衣和内衣
2020/05/26 全球购物
一些Unix笔试题和面试题
2012/09/25 面试题
好邻里事迹材料
2014/01/16 职场文书
销售内勤岗位职责
2014/04/15 职场文书
环保专项行动方案
2014/05/12 职场文书
会计求职信范文
2014/05/24 职场文书
社区巾帼文明岗事迹材料
2014/06/03 职场文书
争做文明公民倡议书
2014/08/29 职场文书
能用CSS实现的就不要麻烦JavaScript了
2021/10/05 HTML / CSS
Java异常处理try catch的基本用法
2021/12/06 Java/Android
Java异常体系非正常停止和分类
2022/06/14 Java/Android