• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    EXTJS记事本 当CompositeField遇上RowEditor

    发布者: 涵韵3588 | 发布时间: 2025-8-13 13:13| 查看数: 21| 评论数: 0|帖子模式

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

    }

    ]


    }


    ]

    谨以此记,分享给有需要的朋友
    来源:互联网
    免责声明:如果侵犯了您的权益,请联系站长(1277306191@qq.com),我们会及时删除侵权内容,谢谢合作!

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

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