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 相关文章推荐
Javascript-Mozilla和IE中的一个函数直接量的问题
Jan 09 Javascript
写得不错的jquery table鼠标经过变色代码
Sep 27 Javascript
javascript中直接引用Microsoft的COM生成Word
Jan 20 Javascript
jquery选择器之属性过滤选择器详解
Jan 27 Javascript
JavaScript 模块化编程(笔记)
Apr 08 Javascript
jQuery实现的fixedMenu下拉菜单效果代码
Aug 24 Javascript
js实现的彩色方块飞舞奇幻效果
Jan 27 Javascript
jQuery插件学习教程之SlidesJs轮播+Validation验证
Jul 12 Javascript
浅谈js的异步执行
Oct 18 Javascript
JS作用域链详解
Jun 26 Javascript
laydate只显示时分 不显示秒的功能实现方法
Sep 28 Javascript
vue中如何自定义右键菜单详解
Dec 08 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
手把手教你使用DedeCms V3的在线采集图文教程
2007/04/03 PHP
PHP 5.0对象模型深度探索之类的静态成员
2008/03/27 PHP
php通过Chianz.com获取IP地址与地区的方法
2015/01/14 PHP
php三元运算符知识汇总
2015/07/02 PHP
PHP实现的支付宝支付功能示例
2019/03/26 PHP
User Scripts: Video Download by User Scripts
2007/05/14 Javascript
JQuery 无废话系列教程(一) jquery入门 [推荐]
2009/06/23 Javascript
html 锁定页面(js遮罩层弹出div效果)
2009/10/27 Javascript
突发奇想的一个jquery插件
2010/11/19 Javascript
js 代码优化点滴记录
2012/02/19 Javascript
多个js与css文件的合并方法详细说明
2012/12/26 Javascript
Query中click(),bind(),live(),delegate()的区别
2013/11/19 Javascript
jQuery中 prop() attr()使用详解
2015/05/19 Javascript
jQuery实现的网页右下角tab样式在线客服效果代码
2015/10/23 Javascript
JS组件Bootstrap Table表格行拖拽效果实现代码
2020/08/27 Javascript
Html中 IFrame的用法及注意点
2016/12/22 Javascript
JavaScript运动框架 多物体任意值运动(三)
2017/05/17 Javascript
javascript中的replace函数(带注释demo)
2018/01/07 Javascript
javascript与PHP动态往类中添加方法对比
2018/03/21 Javascript
基于vue实现一个神奇的动态按钮效果
2019/05/15 Javascript
微信小程序3D轮播实现代码
2019/09/19 Javascript
python实现猜数字游戏(无重复数字)示例分享
2014/03/29 Python
分数霸榜! python助你微信跳一跳拿高分
2018/01/08 Python
Django权限机制实现代码详解
2018/02/05 Python
创建pycharm的自定义python模板方法
2018/05/23 Python
Python字典创建 遍历 添加等实用基础操作技巧
2018/09/13 Python
python使用itchat模块给心爱的人每天发天气预报
2019/11/25 Python
python 比较字典value的最大值的几种方法
2020/04/17 Python
使用opencv中匹配点对的坐标提取方式
2020/06/04 Python
Python调用百度OCR实现图片文字识别的示例代码
2020/07/17 Python
解决python运行效率不高的问题
2020/07/20 Python
Python用户自定义异常的实现
2020/12/25 Python
搬家公司的创业计划书
2014/01/01 职场文书
公司建议书怎么写
2014/05/15 职场文书
2016寒假社会实践心得体会范文
2015/10/09 职场文书
导游词书写之黄山
2019/08/06 职场文书