Javascript 在ExtJs 3.3组合框中显示多个字段

Javascript 在ExtJs 3.3组合框中显示多个字段,javascript,extjs,combobox,extjs3,Javascript,Extjs,Combobox,Extjs3,我已经打开了一个ExtJs项目,我已经有一段时间没有想到它了,这让我很困惑 我有一个Ext.form.ComboBox,它使用远程JSON存储来列出用户。我使用XTemplate来格式化下拉列表中列出的用户: '<tpl for="."><div class="x-combo-list-item">', '{firstname} {lastname} ({email})', '</div></tpl>' ”, “{firstname}{lastn

我已经打开了一个ExtJs项目,我已经有一段时间没有想到它了,这让我很困惑

我有一个Ext.form.ComboBox,它使用远程JSON存储来列出用户。我使用XTemplate来格式化下拉列表中列出的用户:

'<tpl for="."><div class="x-combo-list-item">',
'{firstname} {lastname} ({email})',
'</div></tpl>'
”,
“{firstname}{lastname}({email})”,
''
当我展开下拉列表时,我看到正确列出了我的用户:

约翰·史密斯(jsmith@company.com)

约翰·福特(jford@company.com)

但是,当我单击某个用户时,组合框的内容会更改为您所期望的valueField属性(“firstname”)

问题:

  • 我想让组合框显示:约翰·史密斯,而不是约翰(jsmith@company.com)

  • 当我有两个John(John Smith和John Ford)并加载表单时,ExtJs逻辑将与它在列表中找到的第一个John匹配,并将字段的值更改为它匹配的第一个John

  • 例如: 约翰·史密斯(ID=1) 约翰·福特(ID=2)

    用户选择John Ford,单击组合菜单项后,“John”出现在组合框中,并且用户_id=2被写入数据库

    但是,当我重新加载页面时,名称“John”将匹配(从数据库加载)到第一个列表条目,如果操作员没有在下拉对话框中手动更改选择,则会选择John Smith,此时用户id=1将写入数据库(当用户保存表单时)

    任何意见都将不胜感激。我的直觉告诉我,在load和post列表单击期间应该有几个钩子,这将允许我操作写入元素的innerHTML元素的内容

    ~~~~~~~~~~~~~

    注意:我继承了一个自定义类,该类允许我提前键入对、firstname、lastname和电子邮件地址的查询(因为我们可能有数百个用户要搜索)

    我从中继承的ComboBox元素:

    CW.form.CustomComboBox = Ext.extend( Ext.form.ComboBox, {
    
    filterKeys:[],
    
    // Note: This overrides the standard doQuery function in Ext 3.3
    doQuery: function(q, forceAll){
    
        q = Ext.isEmpty(q) ? '' : q;
        var qe = {
            query: q,
            forceAll: forceAll,
            combo: this,
            cancel:false
        };
        if(this.fireEvent('beforequery', qe)===false || qe.cancel){
            return false;
        }
        q = qe.query;
        forceAll = qe.forceAll;
        if(forceAll === true || (q.length >= this.minChars)){
            if(this.lastQuery !== q){
                this.lastQuery = q;
                if(this.mode == 'local'){
                    this.selectedIndex = -1;
                    if(forceAll){
                        this.store.clearFilter();
                    }else{
                        // this.store.filter(this.displayField, q);
                        this.store.filterBy( function(rec,id){
                            return this.filterFn(rec,id,q);
                        }, this );
                    }
                    this.onLoad();
                }else{
                    this.store.baseParams[this.queryParam] = q;
                    this.store.load({
                        params: this.getParams(q)
                    });
                    this.expand();
                }
            }else{
                this.selectedIndex = -1;
                this.onLoad();
            }
        }
    },
    
    /**
     * Custom function for filtering the store
     */
    filterFn: function(rec, id, q ){
    
        // var filterKeys = ['id', 'firstname', 'lastname', 'email'];
        var parts = q.split(' ');
    
        // If no filter applied then show no results
        if(parts.length == 0){
            return false;
        }
    
        // Iterate through each of the parts of the user string
        // They must all match, at least in part, one of the filterKeys
        // (i.e. id, email, firstname, etc.)
        for(i=0; i<parts.length;i++){
            var foundPart = false;
    
            // Create a RegExp object for this search snippet (i.e. '@gmai')
            var matcher = this.store.data.createValueMatcher(parts[i] , true);
    
            // Search until this matches one of the keys for this record
            for(j=0;j<this.filterKeys.length; j++){
                if(matcher.test(rec.get(this.filterKeys[j]))){
                    foundPart = true;
                    break;
                }
            }
    
            // If there are no fields of the record matching this part,
            // the record does not match (return false)
            if( foundPart == false ){
                return false;
            }
        }
        return true;
    
    },
    
    initComponent: function(){
    
        Ext.applyIf(this,{
            listeners:{
                beforequery: function(qe){
                        delete qe.combo.lastQuery;
                        return true;
                    }          
                }
        });
    
        if(this.filterKeys.length == 0){
            this.filterKeys = [this.displayField];
        }
    
        CW.form.CustomComboBox.superclass.initComponent.call(this);
    
    
    }
    });
    Ext.reg('custom-combo', CW.form.CustomComboBox);
    
    CW.form.CustomComboBox=Ext.extend(Ext.form.ComboBox{
    筛选键:[],
    //注意:这将覆盖Ext3.3中的标准doQuery函数
    doQuery:函数(q,forceAll){
    q=Ext.isEmpty(q)?“”:q;
    var qe={
    问:问:,
    forceAll:forceAll,
    组合:这个,
    取消:假
    };
    if(this.firevent('beforequery',qe)==false | | qe.cancel){
    返回false;
    }
    q=qe.query;
    forceAll=qe.forceAll;
    if(forceAll==true | |(q.length>=this.minChars)){
    if(this.lastQuery!==q){
    this.lastQuery=q;
    如果(this.mode=='local'){
    this.selectedIndex=-1;
    如果(全部强制){
    this.store.clearFilter();
    }否则{
    //this.store.filter(this.displayField,q);
    this.store.filterBy(函数(rec,id){
    返回此.filterFn(rec,id,q);
    },这个);
    }
    这个.onLoad();
    }否则{
    this.store.baseParams[this.queryParam]=q;
    这个。存储。加载({
    params:this.getParams(q)
    });
    这个。展开();
    }
    }否则{
    this.selectedIndex=-1;
    这个.onLoad();
    }
    }
    },
    /**
    *用于筛选存储的自定义函数
    */
    filterFn:函数(rec、id、q){
    //var filterKeys=['id'、'firstname'、'lastname'、'email'];
    var部分=q.分割(“”);
    //如果未应用任何过滤器,则不显示任何结果
    如果(parts.length==0){
    返回false;
    }
    //遍历用户字符串的每个部分
    //它们必须全部匹配(至少部分匹配)一个筛选键
    //(即id、电子邮件、名字等)
    对于(i=0;i关于问题#1,我发现获得良好自定义显示字段的最佳方法是在商店使用的Ext.data.Record定义中使用生成的字段。这样,您就可以访问完整记录来创建显示字段,而不仅仅限于一个字段。现在Sencha正在继续,我无法在线找到3.x示例到Ext4,但您可以在ExtJS下载的
    examples/form
    目录中找到此示例。这里我修改了一个ExtJS组合示例(
    examples/form/combo.js
    ):

    现在,组合框显示值,如
    Texas-TX
    ,或任何您拥有的
    convert
    输出。您可以在中找到
    convert
    的文档


    至于问题2,如果您使用的是便利的store+Reader组合,如JsonStore或ArrayStore,您可能需要为Ext.data.Reader或您的store设置
    idProperty
    idProperty
    告诉Ext要查找唯一标识符的字段。如果没有
    i,您可能会出现各种奇怪的行为d属性
    或您选择一个非唯一的属性。文档是唯一的。

    您只需用以下代码替换显示字段

    tpl: Ext.create('Ext.XTemplate',
        '<tpl for=".">',
            '<div class="x-boundlist-item">{firstName} {lastName} {email}</div>',
        '</tpl>'
    ),
    // template for the content inside text field
    displayTpl: Ext.create('Ext.XTemplate',
        '<tpl for=".">',
            'firstName} {lastName} {email}',
        '</tpl>'
    )
    
    tpl:Ext.create('Ext.XTemplate',
    '',
    “{firstName}{lastName}{email}”,
    ''
    ),
    //文本字段内内容的模板
    displayTpl:Ext.create('Ext.XTemplate',
    '',
    'firstName}{lastName}{email}',
    ''
    )
    
    太棒了,工作起来很有魅力。关于第2点-我确实设置了IDproperty,但粗略的测试表明,由于您对第1点的解决方案,它已被修复。干杯!感谢此解决方案,它对我的一个项目非常有用:)当我单击下拉菜单时,它对我起到了部分作用,下拉菜单中显示的是displayField值,而不是xtemplete值。
    tpl: Ext.create('Ext.XTemplate',
        '<tpl for=".">',
            '<div class="x-boundlist-item">{firstName} {lastName} {email}</div>',
        '</tpl>'
    ),
    // template for the content inside text field
    displayTpl: Ext.create('Ext.XTemplate',
        '<tpl for=".">',
            'firstName} {lastName} {email}',
        '</tpl>'
    )