2013-07-29 88 views
1

我正在为Ext.js提供Search-As-You组件。它具有AND-过滤几个单词,每个单词与记录的任何属性进行OR过滤,后来。 当我键入“可巴”时,它会过滤为“凯文培根”和“贝基肯尼迪”。Extjs Combobox在存储加载无结果时保持重置文本值

我正在加载远程模式下的初始数据集。

会发生什么情况是数据通过我的REST代理和JSON阅读器加载到商店中。目前,我不在服务器端“过滤”,但返回所有内容并模拟客户端中的过滤器,就好像数据集已从服务器过滤一样。所以它似乎是组合框。

现在,当我将搜索字符串更改为“Kre Ba”时,它将从REST-API(所有数据)重新加载,但Store对于组合框将是空的,因为我没有任何记录匹配“Kre Ba”。

不知何故,Ext-js决定重置组合框的值,整个搜索字符串消失。

即使商店在过滤之后没有匹配的商品(价值明智),是否有一种简洁的方式来保持搜索字符串?!

这里是Ext.js代码,我发现,重置价值:

onLoad: function(store, records, success) { 
    var me = this; 

    if (me.ignoreSelection > 0) { 
     --me.ignoreSelection; 
    } 

    // If not querying using the raw field value, we can set the value now we have data 
    if (success && !store.lastOptions.rawQuery) { 
     // Set the value on load 

     // There's no value. 
     if (me.value == null) { 
      // Highlight the first item in the list if autoSelect: true 
      if (me.store.getCount()) { 
       me.doAutoSelect(); 
      } else { 
       // assign whatever empty value we have to prevent change from firing 
       me.setValue(me.value); 
      } 
     } else { 
      me.setValue(me.value); 
     } 
    } 
}, 

在调试过程中我发现,对于检查me.store.getCount()回报false

UPDATE:

这里是我的组合框的配置:

Ext.define('MyApp.view.SearchAsYouTypeCombobox', { 
extend: 'Ext.form.field.ComboBox', 
alias: 'widget.SearchAsYouTypeCombobox', 

fieldLabel: 'Label', 
hideLabel: true, 
emptyText: 'Search', 
hideTrigger: true, 
minChars: 3, 

initComponent: function() { 
    var me = this; 

    Ext.applyIf(me, { 
      //some templates 
    }); 

    me.callParent(arguments); 
} 

}); 

我想建立组件作为控制器,你只需要配置一个组合框的视图和存储:

Ext.define('MyApp.controller.SearchAsYouTypeComboboxController', { 
extend: 'Ext.app.Controller', 

stores: [ 
    'SearchAsYouTypeStore' 
], 
views: [ 
    'SearchAsYouTypeCombobox' 
], 

onComboboxBeforeQuery1: function(queryPlan, eOpts) { 
    var me = this; 
    //determine tokens 
    //add filter per token 

    //One could optimize by not clearing the filter when the query String is only extended (leading or trailing) and not changed. 
    //consider maybe the tokens 

    //console.log('beforeQuery'); 
    var comboBox = queryPlan.combo; 
    var myStore = comboBox.getStore(); 

    var queryString = queryPlan.query; 
    var prevQueryString = comboBox.lastQuery || ''; 

    var words = Ext.String.splitWords(queryString); 

    //var filterAllPropertiesFilter = {}; 


    console.log('Query String :' + queryString); 
    console.log("Words: " + words); 

    //console.log(Ext.JSON.encode(myStore.storeId)); 

    //myStore.clearFilter(true); 

    if(!Ext.isEmpty(queryString)) 
    { 
     var filters = []; 


     //When query has not been only expanded 
     if(prevQueryString && 
     (queryString.length <= prevQueryString.length || 
     queryString.toLowerCase().lastIndexOf(prevQueryString.toLowerCase(), 0) !== 0)) 
     { 
      //Reload everything new 
      myStore.remoteFilter = true; 
      myStore.clearFilter(true); //careful with this, it loads all the data unfiltered! 


      myStore.remoteFilter = false; 
      console.log('Creating Filters for each word.'); 
      Ext.Array.each(words, 
      function(word, index, allWords){ 
       me.currentFilterWord = word; 
       console.log('NEW FILTER: word:' + word); 

       var filterAllPropertiesFilter = Ext.create('Ext.util.Filter', 
        {filterString: word, 
        filterFn: me.filterAllPropertiesFn}); 
       filters.push(filterAllPropertiesFilter); 

      }); 

     } 
     else{ 
      if(!prevQueryString){ 
       myStore.remoteFilter = true; 
       myStore.clearFilter(); 
      } 
      myStore.remoteFilter = false; 

      //only for the last word 
      me.currentFilterWord = words[words.length-1]; 
      console.log('NEW FILTER: word: ' + me.currentFilterWord); 

      var filterAllPropertiesFilter = Ext.create('Ext.util.Filter', 
       {filterString: me.currentFilterWord, 
       filterFn: me.filterAllPropertiesFn}); 

      filters.push(filterAllPropertiesFilter); 
      Ext.Array.each(myStore.filters.items, 
      function(filter, index, allFilters){ 
       myStore.removeFilter(filter, false); 
      }); 
      //myStore.filter(filterAllPropertiesFilter); 
     } 

     myStore.filter(filters); 
     comboBox.lastQuery = queryString; 
     //filterBy(filters); 
    } 
    else 
    { 
     myStore.clearFilter(false); 
    } 

    comboBox.expand(); 
    queryPlan.cancel = true; 
    return queryPlan; 
}, 

filterAllPropertiesFn: function(item) { 
    // filter magic 
}, 

filterOverride: function(filters, value) { 
    //changed the filter to subsequently filter 
}, 

init: function(application) { 
    var me = this; 
    console.log("init of Controller"); 

    //when more than 1 store then error 
    console.log("Stores: " + this.stores[0]); 

    var myStoreName = this.stores[0]; 
    var MyStore = me.getStore(myStoreName); 

    console.log("MyStore: " + MyStore.storeId); 

    Ext.override(MyStore,{override: myStoreName, 
    filter: me.filterOverride}); 

    var myComboBoxName = this.views[0]; 
    var MyComboBox = me.getView(myComboBoxName); 

    console.log("MyComboName: " + myComboBoxName); 
    console.log("Data: " + MyStore.data.collect('id')); 

    MyComboBox.store = MyStore; 
    Ext.override(MyComboBox, {override: myComboBoxName, 
    store: MyStore}); 

    console.log("myCombo.store: " + MyComboBox.store.storeId); 


    this.control({ 
     "combobox": { 
      beforequery: this.onComboboxBeforeQuery1, 
     } 
    }); 
}, 
}); 
+0

什么是您的组合框的配置是什么样子?即你有lastQuery:'',triggerAction:'all'和forceSelection:false set? – radtad

+0

我已经在问题中添加了它们。谢谢。 – haynzz

回答

0

我做了一些尝试和错误...

它似乎工作知道这些更改组合框beforequery方法。但不知何故,它不会在第一次本地过滤之后“自动选择”第一场比赛。

onComboboxBeforeQuery1: function(queryPlan, eOpts) { 
    var me = this; 

    var comboBox = queryPlan.combo; 
    var myStore = comboBox.getStore(); 

    var queryString = queryPlan.query; 
    var prevQueryString = comboBox.lastQuery || ''; 

    var words = Ext.String.splitWords(queryString); 

    console.log('Query String :' + queryString); 
    console.log("Words: " + words);A 


    if(!Ext.isEmpty(queryString)) 
    { 
     var filters = []; 


     //When query string has not just only expanded 
     if(prevQueryString && 
     (queryString.length <= prevQueryString.length || 
     queryString.toLowerCase().lastIndexOf(prevQueryString.toLowerCase(), 0) !== 0)) 
     { 
      //Reload everything new 
      //myStore.remoteFilter = true; 
      myStore.clearFilter(false); 
      //myStore.load(); 


      //myStore.remoteFilter = false; 
      console.log('Creating Filters for each word.'); 
      Ext.Array.each(words, 
      function(word, index, allWords){ 
       me.currentFilterWord = word; 
       console.log('NEW FILTER: word:' + word); 

       var filterAllPropertiesFilter = Ext.create('Ext.util.Filter', 
        {filterString: word, 
        filterFn: me.filterAllPropertiesFn}); 
       filters.push(filterAllPropertiesFilter); 

      }); 

     } 
     else{ 
      if(!prevQueryString){ 
       myStore.remoteFilter = true; 
       myStore.clearFilter(); 
      } 
      myStore.remoteFilter = false; 

      //only for the last word 
      me.currentFilterWord = words[words.length-1]; 
      console.log('NEW FILTER: word: ' + me.currentFilterWord); 

      var filterAllPropertiesFilter = Ext.create('Ext.util.Filter', 
       {filterString: me.currentFilterWord, 
       filterFn: me.filterAllPropertiesFn}); 

      filters.push(filterAllPropertiesFilter); 
      Ext.Array.each(myStore.filters.items, 
      function(filter, index, allFilters){ 
       myStore.removeFilter(filter, false); 
      }); 
     } 

     myStore.filter(filters); 
     comboBox.lastQuery = queryString; 
    } 
    else 
    { 
     myStore.clearFilter(false); 
    } 

    comboBox.expand(); 
    queryPlan.cancel = true; 
    return queryPlan; 
} 
0

我认为你想要做太多。如果你扩展组合框,为什么不重写你需要使用的一个函数?

例如,我有类似的功能,你想为你的组合框写一些东西。我在autoLoad上有一个组合商店来获取数据。在那之后,如果我输入任何东西,它会强制doLocalQuery被解雇,因为我有queryMode:'local'。我重写该函数和更换一个部分:

var me = this, 
     queryString = queryPlan.query, 
     picker = me.getPicker(); 

    /** 
    * @author tjohnston 
    * added queryPlan to combo so we can use it later 
    * added query and caseSensitive to picker (boundlist) to use in highlighting 
    */ 
    me.queryPlan = queryPlan; 
    picker.query = queryString; 
    picker.caseSensitive = me.caseSensitive; 

    // Create our filter when first needed 
    if (!me.queryFilter) { 
     // Create the filter that we will use during typing to filter the Store 
     me.queryFilter = new Ext.util.Filter({ 
      id: me.id + '-query-filter', 
      anyMatch: me.anyMatch, 
      combo: me, 
      caseSensitive: me.caseSensitive, 
      root: 'data', 
      /** 
      * removed property as we're using filterFn 
      * added filterFn functionality 
      */ 
      /** property: me.displayField, **/ 
      filterFn: function(rec) { 
       return me.filterFn(me,rec); 
      } 
     }); 
     me.store.addFilter(me.queryFilter, false); 
    } 

这则依次调用两个功能:

/** @public **/ 
/** config for any instance we create if we want to override. **/ 
filterTest: function(combo,str,regex,rec) { 
    return regex.test(rec.data[combo.displayField]); 
}, 

/** @private **/ 
/** our filter function for **/ 
filterFn: function(combo,rec) { 
    var me = this, 
     queryPlan = combo.queryPlan, 
     anyMatch = me.anyMatch, 
     caseSensitive = me.caseSensitive ? '' : 'i', 
     queryString = anyMatch ? queryPlan.query.split(/\s+/) : '^'+queryPlan.query, 
     total = queryString.length, 
     isNoMatch = 0, 
     isMatch = 0, 
     i = 0; 

    /** make sure we filter for each text string in the query **/ 
    Ext.each(queryString, function(str) { 
     if (str !== '') { 
     //if (str !== '' && str.length >= combo.minChars) { 
      var query = new RegExp(str,caseSensitive+'g'); 
      if (combo.filterTest(combo,str,query,rec)) { 
       isMatch++; 
      } else { 
       isNoMatch++; 
      } 
     } 
    }); 

    if (isNoMatch > 0) { 
     /** we match in OR so if we have one match from any query word, return true **/ 
     if (combo.orMatch == true && isMatch > 0) { 
      return true; 
     } 
     return false; 
    } else { 
     return true; 
    } 
}, 
+0

'combo.queryPlan'似乎没有被定义。我是否缺少组合选项?否则,我现在只需将它设置在beforeQuery中。 – haynzz

+0

此解决方案每次都在“已加载”记录上应用所有过滤器。它没有随后丢失记录的议程,而搜索字符串仅被扩展(在中间没有改变)。 – haynzz

+0

你可以忽略combo.queryPlan。我将它添加到行(!me.queryFilter)之前。如果你想在上面添加它:\t me.queryPlan = queryPlan; picker.query = queryString; picker.caseSensitive = me.caseSensitive; – radtad

相关问题