EXTJS记事本 当CompositeField遇上RowEditor

原因是客户的物料种类非常多,有一千种之多,如果单纯用一个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

}

]

}

]

谨以此记,分享给有需要的朋友

(0)

相关推荐

  • Python基于Tkinter实现的记事本实例

    本文实例讲述了Python基于Tkinter实现的记事本.分享给大家供大家参考.具体如下: from Tkinter import * root = Tk('Simple Editor') mi=StringVar() Label(text='Please input something you like~' ).pack() te = Text(height = 30,width =100) te.pack() Label(text=' File name ').pack(side = LEF

  • 使用Java制作一个简单的记事本

    通过使用Java的Swing.IO来实现一个简单记事本,实现打开指定的text文本文件,然后将text文件的内容加载到Swing组件中,然后在Swing组件中编辑记事本内容,然后同菜单的保存选项将编辑后的内容保存到text文件中.代码如下: 复制代码 代码如下: import java.io.*; import java.nio.*; import java.nio.channels.*; import java.nio.charset.*; import java.awt.*; import

  • VB简易记事本实现代码

    事件实现代码: 复制代码 代码如下: Private Sub mQuit_Click() Text1.Text = "" End End Sub Private Sub mNew_Click() Text1.Text = "" Form1.Caption = "未命名" End Sub Private Sub mopen_Click() CommonDialog1.ShowOpen Frame = CommonDialog1.FileName I

  • Android实现记事本功能(26)

    本文实例为大家分享了Android实现记事本功能的具体代码,供大家参考,具体内容如下 MainActivity.java代码: package siso.smartnotef.activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.support.

  • 简单记事本java源码实例

    本文实例讲述了简单记事本java实现代码.分享给大家供大家参考.具体如下: 完整代码如下: 复制代码 代码如下: import java.awt.*; import java.io.*; import java.awt.datatransfer.*; import java.awt.event.*;   public class Main extends Frame implements ActionListener {         private static final long ser

  • 使用记事本编写java程序全过程图解

    Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaSE, JavaEE, JavaME)的总称.Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于个人PC.数据中心.游戏控制台.科学超级计算机.移动电话和互联网,同时拥有全球最大的开发者专业社群. 新建java第一种方法 1首先右击鼠标,新建一个文本文档. 2更改文本文档的后缀名为 .java .注意文件名必

  • python3.5使用tkinter制作记事本

    tkinter是Python下面向tk的图形界面接口库,可以方便地进行图形界面设计和交互操作编程.tkinter的优点是简单易用.与Python的结合度好.tkinter在Python 3.x下默认集成,不需要额外的安装操作:不足之处为缺少合适的可视化界面设计工具,需要通过代码来完成窗口设计和元素布局. 本节采用的Python版本为3.x,如果想在python 2.x下使用tkinter,请通过apt-get进行安装.需要注意的是,不同Python版本下的tkinter使用方式可能略有不同,建议

  • A notepad made in HTA(hta实现的记事本)

    This notepad can handle bigger files than the one shiped with Win9x. Learn how to make windows looking interfaces in HTML. Interesting use of Commondialogs. 效果图: 复制代码 代码如下: <html><head> <HTA:APPLICATION APPLICATIONNAME="HTANotePad"

  • Excel、记事本数据导入到数据库的实现方法

    文件示例:Excel: 记事本: 前台代码: 复制代码 代码如下: <div class="tab-content detail" id="divSecond" runat="server" visible="false">            <fieldset >             <p>                <label>                 

  • 怎么运行用记事本写的java程序

    今天用记事本写了一个java程序,测试能运行,现在把它分解成几个步骤,利于大家理解: 1. 新建一个记事本,后缀名是  .java  :然后在里面写一段java的代码,如图: 2.把写好的java文件丢进D盘,就是第一步给出的那个class文件: 3. 打开dos界面 开始-〉运行-〉cmd-〉 这个是命令行模式,选择D盘,如图: 4.选择D盘之后,在命令提示符中输入"javac 文件名.java",我的文件名为java,所以输入javac java.java然后回车,等待编译.这时候

随机推荐