EXTJS记事本:当CompositeField遇上RowEditor

用RowEditor作批量编辑器时,遇到一个问题,想要在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
                
            }
            
            ]

        
                  }
                                            
               
                    ]
        

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

转载于:https://www.cnblogs.com/Heroman/archive/2011/07/30/2122269.html

你可能感兴趣的:(EXTJS记事本:当CompositeField遇上RowEditor)