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 相关文章推荐
表单填写时用回车代替TAB的实现方法
Oct 09 Javascript
js点击文本框弹出可选择的checkbox复选框
Feb 03 Javascript
JavaScript实现页面跳转的方式汇总
May 16 Javascript
AnjularJS中$scope和$rootScope的区别小结
Sep 18 Javascript
D3.js实现散点图和气泡图的方法详解
Sep 21 Javascript
微信公众号开发 实现点击返回按钮就返回到聊天界面
Dec 15 Javascript
JS运动特效之同时运动实现方法分析
Jan 24 Javascript
浅谈在react中如何实现扫码枪输入
Jul 04 Javascript
对vue事件的延迟执行实例讲解
Aug 28 Javascript
vue实现简单的日历效果
Sep 24 Javascript
jquery更改元素属性attr()方法操作示例
May 22 jQuery
javascript实现智能手环时间显示
Sep 18 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
php5.2以下版本无json_decode函数的解决方法
2014/05/25 PHP
PHP链表操作简单示例
2016/10/15 PHP
PHP array_shift()用法实例分析
2019/01/07 PHP
php 使用mpdf实现指定字段配置字体样式的方法
2019/07/29 PHP
javascript 事件绑定问题
2011/01/01 Javascript
Javacript实现颜色梯度变化和渐变的效果代码
2013/05/31 Javascript
jQuery中data()方法用法实例
2014/12/27 Javascript
检测一个函数是否是JavaScript原生函数的小技巧
2015/03/13 Javascript
JavaScript对象属性检查、增加、删除、访问操作实例
2015/07/08 Javascript
AngularJS动态生成div的ID源码解析
2016/08/29 Javascript
jQuery事件对象总结
2016/10/17 Javascript
Bootstrap基本样式学习笔记之按钮(4)
2016/12/07 Javascript
angular和BootStrap3实现购物车功能
2017/01/25 Javascript
vue按需引入element Transfer 穿梭框
2017/09/30 Javascript
node crawler如何添加promise支持
2020/02/01 Javascript
js实现消灭星星(web简易版)
2020/03/24 Javascript
ant design 日期格式化的实现
2020/10/27 Javascript
python比较2个xml内容的方法
2015/05/11 Python
简单介绍Python的Django框架的dj-scaffold项目
2015/05/30 Python
Python随机生成数据后插入到PostgreSQL
2016/07/28 Python
浅谈Python的list中的选取范围
2018/11/12 Python
Python Tkinter 简单登录界面的实现
2019/06/14 Python
Python中的支持向量机SVM的使用(附实例代码)
2019/06/26 Python
Django分页功能的实现代码详解
2019/07/29 Python
Python实现汇率转换操作
2020/05/03 Python
皇马官方商城:Real Madrid Store
2016/09/02 全球购物
美国网上鞋子零售商:Dr. Scholl’s Shoes
2017/11/17 全球购物
泰海淘:泰国king Power王权免税集团旗下跨境海淘综合型电商
2020/07/26 全球购物
大学生职业生涯规划书模板
2014/01/03 职场文书
会计专业毕业自荐书范文
2014/02/08 职场文书
先进基层党组织事迹材料2016
2016/02/29 职场文书
小学语文教学反思范文
2016/03/03 职场文书
受欢迎的自荐信,就这么写!
2019/04/19 职场文书
年中了,该如何写好个人述职报告?
2019/07/02 职场文书
Python+Tkinter打造签名设计工具
2022/04/01 Python
Java数组详细介绍及相关工具类
2022/04/14 Java/Android