Discuz教程网

EXTJS记事本 当CompositeField遇上RowEditor

[复制链接]
authicon dly 发表于 2011-9-16 07:57:38 | 显示全部楼层 |阅读模式
原因是客户的物料种类非常多,有一千种之多,如果单纯用一个Combobox,那么在实际使用中,很难快速找到一个物料,所以,我使用包含物料分类和物料品牌的两个combobox来组成级联式筛选。问题恰恰出在这儿,如果在roweditor的一个字段中用多个控件,就要处理每个控件的初始化,Change事件。网上目前还未找到有人有好的解决办法。经过3天的调试,我终于解决了问题,把我的代码贴出来:
  1. var editor=new Ext.ux.grid.RowEditor({
  2. saveText: '确定',
  3. cancelText:"放弃",
  4. commitChangesText: '请确定或放弃修改',
  5. errorText: '错误'
  6. });
  7. //当取消时,根据关键字段的值是否为空而删掉空记录
  8. editor.on("canceledit",function(editor,pressed)
  9. {
  10. if(pressed && editor.record.get("materialid")==0)
  11. {
  12. store.remove(editor.record);
  13. }
  14. },this);
  15. /*
  16. afterstart 这个事件是自己加的,因为如果在beforeedit事件中想对自己的控件初始化,那是不可能的,因为beforeedit时,roweditor控件还没有渲染,所以,我加了afterstart事件,该事件在roweditor显示后立即调用,所以,可以在这里进行初始化。
  17. 要注意的是通过roweditor控件进行遍历来访问自定义的composite控件
  18. editor.items.items[0],这里并不是我写重了,而是roweditor控件的items竟然不是一个集合,而是一个对象,在这里我也耗了一些时间,最后还是通过firebug输出editor对象发现的
  19. editor.items.items[0]就是compositefield组件,通过该组件的items集合,就可以以标准的形式访问其子组件,接下来,就可以初始化了
  20. 因为最后一个combobox的数据是要通过前两个combobox级联选取后载入的,所以,在这里载入其数据进行初始化,但是注意,我是在callback中执行的,因为jsonstore的load动作是异步的,所以,必须通过callback事件的回调在数据载入成功后,再用setValue来初始化值
  21. */
  22. editor.on("afterstart",function(editor,rowIndex)
  23. {
  24. var record=store.getAt(rowIndex);
  25. editor.items.items[0].items.items[0].setValue(record.get("setid"));
  26. editor.items.items[0].items.items[1].setValue(record.get("category"));
  27. var t_store=editor.items.items[0].items.items[2].getStore();
  28. t_store.load({
  29. params:{category:record.get("category"),setid:record.get("setid")},
  30. callback:function(r,options,success){
  31. if (success)
  32. editor.items.items[0].items.items[2].setValue(record.get("materialid"));
  33. }
  34. });
  35. },this);
  36. /*
  37. validateedit事件是在按了确认时执行的,用来验证roweditor中各控件的值,在这里,我执行了一个自定义的验证动作,因为我不想用户可以添加重复的物料,所以,我通过遍历jsonstore,将每条记录的物料值与用户选择的物料值进行比较,如果发现已经存在,则提示用户不要重复加入
  38. */
  39. editor.on("validateedit",function(editor,obj,record,rowIndex){
  40. var materialid=editor.items.items[0].items.items[2].getValue();
  41. var exist=false;
  42. Ext.each(store.getRange(),function(o,i){
  43. if(o!=record&&o.get("materialid")==materialid)
  44. {
  45. exist=true;
  46. return(false);
  47. }
  48. });
  49. if(exist)
  50. {
  51. Ext.MessageBox.alert("系统提示","请勿重复添加");
  52. store.remove(record);
  53. }
  54. return(!exist);
  55. },this);
  56. /*
  57. afterEdit是通过验证后执行的,这里最重要的动作是将正在编辑的记录的某些属性赋值,原因是由于采用了compsitefield,所以,roweditor无法将选取的值赋给record的正确属性,需要我们手工将用户的选择赋给相应的字段,materialid就是用户选的物料编号,而model对应是该物料的型号
  58. 为什么要赋model呢?因为model是列的值嘛,不赋的话,显示的是空的
  59. */
  60. editor.on("afteredit",function(editor,obj,record,rowIndex){
  61. record.set("materialid",editor.items.items[0].items.items[2].getValue());
  62. record.set("model",editor.items.items[0].items.items[2].getRawValue());
  63. },this);
复制代码

以上是roweditor的定义和对事件的处理,接下来,将roweditor作为插件插入到gridpanel
  1. {
  2. xtype:"grid",
  3. title:"产品BOM",
  4. layout:"fit",
  5. store:store,
  6. enableDragDrop: false,
  7. border: false,
  8. frame:false,
  9. autoScroll:true ,plugins:[editor],
  10. sm:sm,
  11. height:340,
  12. clicksToEdit:2,
  13. autoWidth: true,
  14. viewConfig:{forceFit:true,autoFill:true,markDirty:false}
  15. }
复制代码

接下来,再看看关于gridpanel的列定义,这里,你可以看到composite是如何用的
  1. columns: [{

  2. header: "物料名称/型号",
  3. dataIndex: "model",
  4. width: 200,
  5. menuDisabled: true,
  6. editor:
  7. {
  8. //定义编辑器
  9. xtype:"compositefield",
  10. name:"compositefield",
  11. items:[
  12. {
  13. xtype: "combo",
  14. mode:"local",
  15. name:"sets",
  16. width:80,
  17. fieldLabel: "适用产品品牌",
  18. emptyText:"请选择",
  19. valueField: "id",
  20. lazyInit:false,
  21. value:this.data?this.data.title:"",
  22. hiddenName:"setid",
  23. hiddenValue:this.data?this.data.setid:"",
  24. displayField: "title",
  25. typeAhead: false,
  26. forceSelection: true,
  27. editable:true,
  28. listeners:{
  29. "change":function(combo,newvalue,oldvalue)
  30. {
  31. //处理品牌的change事件,在选取品牌后,重新载入combobox,editor就是前文定义的roweditor的实例
  32. var category=editor.items.items[0].items.items[1];
  33. var material=editor.items.items[0].items.items[2];
  34. var c=category.getValue();
  35. var store=material.getStore();
  36. store.load({
  37. params:{setid:newvalue,category:c},
  38. callback:function(r,options,success){
  39. if (success)
  40. material.setValue("");
  41. }
  42. });
  43. }
  44. },
  45. triggerAction: "all",
  46. store: new Ext.data.JsonStore({
  47. url: "<%=script_path%>data.asp",
  48. root: "data",autoDestroy:true,
  49. remoteSort: true,
  50. listeners:{"load":function(store,records,option){
  51. var s=Ext.data.Record.create([{name:"id",type:"int"},{name:"title",type:"string"}]);
  52. store.add(new s({id:0,title:"通用"}))
  53. }},
  54. baseParams: {op: "setList"},
  55. totalProperty: "total",
  56. autoLoad: true,
  57. fields: ["title","id"]
  58. })
  59. },
  60. {

  61. xtype: "combo",
  62. mode:"local",width:60,
  63. name:"category",
  64. fieldLabel: "类别",
  65. emptyText:"请选择",
  66. valueField: "category",
  67. lazyInit:false,
  68. value:this.data?this.data.category:"",
  69. displayField: "category",
  70. typeAhead: false,forceSelection: true,
  71. triggerAction: "all",
  72. listeners:{
  73. "change":function(combo,newvalue,oldvalue)
  74. {
  75. //处理类别的change事件,在选取品牌后,重新载入combobox,editor就是前文定义的roweditor的实例
  76. var sets=editor.items.items[0].items.items[0];
  77. var material=editor.items.items[0].items.items[2];
  78. var setid=sets.getValue();
  79. var store=material.getStore();
  80. store.load({
  81. params:{category:newvalue,setid:setid},
  82. callback:function(r,options,success){
  83. if (success)
  84. material.setValue("");
  85. }
  86. });
  87. }
  88. },

  89. store: new Ext.data.JsonStore({
  90. url: "<%=script_path%>data.asp",
  91. root: "data",autoDestroy:true,
  92. remoteSort: true,
  93. baseParams: {op: "materialCategoryList"},
  94. totalProperty: "total",
  95. autoLoad: true,
  96. fields: ["category"]
  97. })


  98. },
  99. {
  100. xtype: "combo",
  101. forceSelection: true,
  102. editable:true,
  103. mode:"local",
  104. name:"material",
  105. fieldLabel: "物料",
  106. emptyText:"请选择物料",
  107. valueField: "id",
  108. allowBlank:false,
  109. displayField: "model",
  110. width:250,
  111. lazyInit:false,
  112. typeAhead: false,
  113. triggerAction: "all",
  114. listeners:{
  115. "change":function(combo,newvalue,oldvalue)
  116. {
  117. //这里一定要注意!!!如果没有下面这两句,那你选择后,会发现显示的值不会变化,并且,点了确认,也不能更新。为什么呢?因为roweditor是通过检测record的isdirty属性来决定是不是调用validateedito和afteredit的,它是检测每列对应的控件值是否变化来判断的,由于物料型号这列,对应的是compositefield,所以,我们必须让compositefield值发生变化,roweditor才会调用validedit和afteredit,并且,compositefield的值还会被调用来显示在列里
  118. var comp=editor.items.items[0];
  119. comp.setRawValue(combo.getRawValue());

  120. }
  121. },

  122. store: new Ext.data.JsonStore({
  123. url: "<%=script_path%>data.asp",
  124. root: "data",autoDestroy:true,
  125. remoteSort: true,
  126. baseParams: {op: "materialList"},
  127. totalProperty: "total",
  128. autoLoad: false,
  129. fields: ["model","id"]
  130. })}
  131. ]
  132. }


  133. },
  134. {
  135. header: "数量",
  136. dataIndex: "qty",
  137. width: 50,
  138. menuDisabled: true,
  139. editor: {
  140. xtype: 'numberfield',
  141. minValue:1,
  142. allowDecimals:false
  143. }

  144. }
  145. ,{
  146. header: "颜色",
  147. dataIndex: "color",
  148. width: 60,
  149. menuDisabled: true

  150. }
  151. ,{
  152. header: "尺寸",
  153. dataIndex: "size",
  154. width: 60,
  155. menuDisabled: true

  156. }

  157. ]


  158. }


  159. ]
复制代码

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



上一篇:IE6下focus与blur错乱的解决方案
下一篇:Javascript 类、命名空间、代码组织代码
authicon 灵犀と杺 发表于 2011-9-16 08:05:57 | 显示全部楼层
不知道如何使用?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1314学习网 ( 浙ICP备10214163号 )

GMT+8, 2025-5-2 10:54

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表