extjs7 combobox 根据输入值执行远端查询过滤选项源码分析
版本
extjs 7.4.0 classic
源码
ext-classic/src/form/field/Base.js
// 初始化事件时将onFieldMutation函数绑定到propertychange,textInput事件上
initEvents: function() {
var me = this,
inputEl = me.inputEl,
onFieldMutation = me.onFieldMutation,
events = me.checkChangeEvents,
len = events.length,
i, event;
if (inputEl) {
me.mon(
inputEl, Ext.supports.SpecialKeyDownRepeat ? 'keydown' : 'keypress', me.fireKey, me
);
for (i = 0; i < len; ++i) {
event = events[i];
if (event === 'propertychange') {
me.usesPropertychange = true;
}
if (event === 'textInput') {
me.usesTextInput = true;
}
me.mon(inputEl, event, onFieldMutation, me);
}
}
me.callParent();
}
- 在输入事件后通过延时(配置项queryDelay,默认值500)任务执行查询,避免输入过程中无效查询
ext-classic/src/form/field/ComboBox.js
onFieldMutation: function(e) {
var me = this,
key = e.getKey(),
isDelete = key === e.BACKSPACE || key === e.DELETE,
rawValue = me.inputEl.dom.value,
len = rawValue.length;
// Do not process two events for the same mutation.
// For example an input event followed by the keyup that caused it.
// We must process delete keyups.
// Also, do not process TAB event which fires on arrival.
if (!me.readOnly && (rawValue !== me.lastMutatedValue || isDelete) && key !== e.TAB) {
me.lastMutatedValue = rawValue;
me.refreshEmptyText();
if (len && (e.type !== 'keyup' || (!e.isSpecialKey() || isDelete))) {
me.doQueryTask.delay(me.queryDelay);
}
else {
// We have *erased* back to empty if key is a delete,
// or it is a non-key event (cut/copy)
if (!len && (!key || isDelete)) {
// This portion of code may end up calling setValue will check for change.
// But since it's come from field mutations, we need to respect
// the checkChangeBuffer, so we suspend checks here, it will be handled
// by callParent
++me.suspendCheckChange;
// Essentially a silent setValue.
// Clear our value, and the tplData used to construct a mathing raw value.
if (!me.multiSelect) {
me.value = null;
me.displayTplData = undefined;
}
// If the value is blank we can't have a value
if (me.clearValueOnEmpty) {
me.valueCollection.beginUpdate();
me.pickerSelectionModel.deselectAll();
me.valueCollection.removeAll();
me.valueCollection.endUpdate();
}
// Just erased back to empty. Hide the dropdown.
me.collapse();
// There may have been a local filter if we were querying locally.
// Clear the query filter and suppress the consequences
// (we do not want a list refresh).
if (me.queryFilter) {
me.clearLocalFilter();
}
// When queryCaching if the user deletes the value and then starts typing
// the same filter again, doQuery can erroneously expand the picker without
// filtering first.
me.lastQuery = null;
--me.suspendCheckChange;
}
me.callParent([e]);
}
}
}
- 查询任务
ext-classic/src/form/field/ComboBox.js
// 初始化查询任务
initComponent: function() {
...
me.doQueryTask = new Ext.util.DelayedTask(me.doRawQuery, me);
...
}
// 获取输入值执行查询
doRawQuery: function() {
var me = this,
rawValue = me.inputEl.dom.value;
if (me.multiSelect) {
rawValue = rawValue.split(me.delimiter).pop();
}
me.doQuery(rawValue, false, true);
}
// 执行查询
doQuery: function(queryString, forceAll, rawQuery) {
var me = this,
store = me.getStore(),
filters = store.getFilters(),
// 判断是否可以,以及如何执行查询
queryPlan = me.beforeQuery({
lastQuery: me.lastQuery || '',
query: queryString || '',
rawQuery: rawQuery,
forceAll: forceAll,
combo: me,
cancel: false
}),
refreshFilters;
if (queryPlan !== false && !queryPlan.cancel) {
// 如果包含查询字符串,并且但钱没有查询过滤器(正在执行查询)或与上次查询的过滤器不同,则执行查询
refreshFilters = !!queryString && (!me.queryFilter || me.queryFilter &&
(filters.indexOf(me.queryFilter) < 0));
// 如果与上一次查询相同则展开下拉框
if (me.queryCaching && !refreshFilters && queryPlan.query === me.lastQuery) {
me.getPicker().refresh();
me.expand();
me.afterQuery(queryPlan);
}
// 否则执行查询并重新加载store
else {
me.lastQuery = queryPlan.query;
if (me.queryMode === 'local') {
me.doLocalQuery(queryPlan);
}
else {
me.doRemoteQuery(queryPlan);
}
}
return true;
}
else {
me.startCheckChangeTask();
}
return false;
}
// 执行远端查询,将查询字符串加入到store加载参数中
doRemoteQuery: function(queryPlan) {
var me = this,
loadCallback = function() {
if (!me.destroyed) {
me.afterQuery(queryPlan);
}
};
me.expand();
if (me.pageSize) {
me.loadPage(1, {
rawQuery: queryPlan.rawQuery,
callback: loadCallback
});
}
else {
me.store.load({
params: me.getParams(queryPlan.query),
rawQuery: queryPlan.rawQuery,
callback: loadCallback
});
}
},
// 分页查询
loadPage: function(pageNum, options) {
this.isPaging = true;
this.store.loadPage(pageNum, Ext.apply({
params: this.getParams(this.lastQuery)
}, options));
},
- 默认查询判断函数,如果没有监听事件beforequery,则根据查询字串长度小于最小字符数(配置项minChars,默认值4)则取消查询
ext-classic/src/form/field/ComboBox.js
beforeQuery: function(queryPlan) {
var me = this;
if (me.fireEvent('beforequery', queryPlan) === false) {
queryPlan.cancel = true;
}
else if (!queryPlan.cancel) {
if (queryPlan.query.length < me.minChars && !queryPlan.forceAll) {
queryPlan.cancel = true;
}
}
return queryPlan;
}