您好,欢迎访问一九零五行业门户网

EXTJS记事本 当CompositeField遇上RowEditor_extjs

原因是客户的物料种类非常多,有一千种之多,如果单纯用一个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: 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: 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: 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
}
]
}
]
谨以此记,分享给有需要的朋友
其它类似信息

推荐信息