- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想在组合框中为记录(这是一个历史数据,存储在数据库中并加载到表单中)设置一个显示字段,该记录在数据库中没有条目。
例如,我在商店中有 3 个条目,如下所示 -值:显示字段一个苹果b : 球c : 猫
像往常一样,它用于预填充组合框(到这里工作正常)。
我在数据库中存储了历史数据,其中有一些记录的值id: d,它在商店中不再存在,但我仍然想支持旧数据并想用它显示关联的显示字段('doll')。
我的问题是,即使这条记录不在与组合框关联的商店中,如何设置从数据库中获取记录时的显示字段?目前,我们在 extJs 中没有诸如 setDisplayField 之类的方法,但是我们有一个方法“setValue”可以更改组合框中的值,这是不需要的。
我想在遇到来自数据库的“id =d”时将显示字段更改为“娃娃”。
请帮忙。
谢谢
最佳答案
如果您真正想要的是setDisplayField
方法,那么实际上它存在并且名为setRawValue
。 .
但是,它本身是否足以解决您的问题值得怀疑。的确,你可能会用它来获得正确的显示,但你会失去你的值(value)......
var legacyData = [
{id: 'd', name: "Doll"}
];
var combo = Ext.widget({
renderTo: Ext.getBody()
,xtype: 'combo'
,fieldLabel: "Regular combo"
,valueField: 'id'
,displayField: 'name'
,queryMode: 'local'
,value: 'd'
,store: {
fields: ['id', 'name']
,data: []
,autoLoad: true
,listeners: {
load: function() {
var value = combo.value,
valueField = combo.valueField,
displayField = combo.displayField,
o = Ext.Array.findBy(legacyData, function(data) {
return data[valueField] === value;
});
if (o) {
combo.setRawValue(o[displayField]);
}
// Fail! This will alert 'Doll' instead of 'd'.
//
// If you set forceSelection to true, the value will be cleared
// all together.
//
alert(combo.getValue());
}
}
}
});
如 dbring 所建议的那样,将历史记录添加到组合的存储中确实可以解决您的问题,前提是您愿意让用户选择历史记录。据我了解,情况并非如此,否则您一开始就不会有任何问题...
在检查组合类的代码后,我认为实现您需要的最好方法是覆盖 findRecord
方法。此方法返回的任何记录都将用于更新组合框显示及其值,与此记录是否存在于组合的存储中无关,并且不会影响可以在组合中选择的值。完美!
假设我们已经添加了一个 legacyStore
到我们的组合中,下面是如何覆盖 findRecord
方法来做到这一点:
findRecord: function(field, value) {
var ls = this.legacyStore,
record = this.callParent(arguments);
if (record) {
// found in current store
return record;
} else if (ls) {
// try legacy value store
var idx = ls.findExact(field, value);
return idx !== -1 ? ls.getAt(idx) : false;
} else {
return false;
}
}
现在,我们还有另外几个问题要处理...
首先,如果在调用 findRecord
时未加载遗留存储怎么办?那行不通的。在其普通形式中,如果未加载其存储,组合框将中止其 setValue
方法,并从其 onLoad
方法中回调它。我们应该添加一些代码来为我们的遗留商店复制此行为。
第二个问题更微不足道,但是如果组合是用历史值初始化的,而用户更改了组合的值但又后悔自己的选择怎么办?如果不取消并重新填写整个表格,他们将无法取回原始值。为了避免这种挫败感,我们可以更改组合行为以在清除时恢复其原始值,而不是其最后的值。由于我不知道这是否可取,我们将把它添加为一个选项。
考虑到所有这些,这里是将处理您的特定用例的“ux”的完整代码。
请注意,如果 forceSelection
设置为 true
并且商店是使用 autoLoad 创建的,它包括一个错误的全局修复,该错误会杀死组合框初始值: 真
。有关更多信息,请参阅 this other question .或者,您可以跳过全局修复并将 loading: true
添加到使用 forceSelection: true
的组合的所有商店和遗留商店。
/**
* Fixes the bug with autoLoad: true and forceSelection: true.
*
* See: https://stackoverflow.com/a/14440479/1387519
*/
Ext.define('Ext.ux.fix.data.Store.AutoLoadLoadingState', {
override: 'Ext.data.Store'
,constructor: function() {
this.callParent(arguments);
if (this.autoLoad) {
this.loading = true;
}
}
});
/**
* A combo box with support for legacy values.
*
* Legacy values will be displayed if their value is assigned to the
* combo, but they won't be selectable (nor queryable) by the user.
*/
Ext.define('Ext.ux.form.field.LegacyValueCombo', {
extend: 'Ext.form.field.ComboBox'
,alias: 'widget.legacyvaluecombo'
,requires: [
'Ext.ux.fix.data.Store.AutoLoadLoadingState'
]
/**
* The store that provides legacy values.
*
* @cfg {Ext.data.Store/Object/String}
*/
,legacyStore: undefined
/**
* If `true` and {@link #forceSelection} is also `true`, the
* {@link #originalValue original value} of the field will be restored when
* the field is cleared, instead of the last value.
*
* This may be useful considering that if the combo original value is a
* legacy one, and the user changes this value, they will have no other
* means to get it back afterward.
*
* @cfg {Boolean}
*/
,restoreOriginalValue: true
/**
* Ensure the legacy store is a store instance before initializing the
* combo box.
*/
,initComponent: function() {
var legacyStore = this.legacyStore;
if (legacyStore) {
this.legacyStore = Ext.data.StoreManager.lookup(legacyStore);
}
this.callParent(arguments);
}
/**
* Overridden to return a legacy record if the value is not found in the
* regular store.
*
* This method will only work if both stores have been loaded.
*/
,findRecord: function(field, value) {
var ls = this.legacyStore,
record = this.callParent(arguments);
if (record) {
// found in current store
return record;
} else if (ls) {
// try legacy value store
var idx = ls.findExact(field, value);
return idx !== -1 ? ls.getAt(idx) : false;
} else {
return false;
}
}
/**
* This method is overridden to support the case where the legacy store
* loads after the regular store.
*/
,setValue: function(value) {
var store = this.store,
legacyStore = this.legacyStore;
if (legacyStore) {
// If the legacy store has not been loaded, trigger it.
if (!legacyStore.lastOptions) {
if (!legacyStore.loading) {
legacyStore.load();
}
}
// Legacy store is loading, we must wait for it to be done before
// processing the value.
if (legacyStore.loading) {
// This is done in the parent setValue method, but we are not
// sure it will be called in time so we must replicate this
// code here.
this.value = value;
this.setHiddenValue(value);
// If the regular store is loading, then this method will be
// called again when it is done. We will see at this time if we
// still have to wait for the legacy store. In the other case,
// we have to simulate a call to onLoad when the legacy store
// has loaded.
if (!store.loading) {
legacyStore.on({
single: true
,scope: this
,load: function(legacyStore, records, success) {
this.onLoad(store, store.getRange(), success);
}
});
}
}
// Legacy store is loaded, that's OK to continue.
else {
this.callParent(arguments);
// Implements restoreOriginalValue.
if (this.restoreOriginalValue) {
this.lastSelection = this.originalValue;
}
}
// setValue must return this
return this;
}
// No legacy store, just defer to the super method.
else {
return this.callParent(arguments);
}
}
});
最后,这是一个 live demo大量示例证明此用户体验适用于同步和异步存储以及 forceSelection
的所有组合...而 setRawValue
则不然。
关于javascript - EXT JS : In Combobox, 如何为不在商店中的记录设置显示字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19058128/
我是一名优秀的程序员,十分优秀!