EXT JS :在组合框中,如何为不在存储中的记录设置显示字段
EXT JS : In Combobox, how to set a displayfield for a record which is not in the store?
我想在组合框中为数据库中没有条目的记录(这是历史数据,存储在数据库中并加载到表单上(设置一个显示字段。
例如,我在商店中有 3 个条目,如下所示 -值:显示字段A : 苹果B : 球C : 猫
像往常一样,它用于预填充组合框(直到这里工作正常(。
我的历史数据存储在数据库中,其中有一些记录的值id:d,商店中不再存在,但我仍然想支持旧数据,并希望显示相关的显示字段("娃娃"(。
我的问题是,即使此记录不在与组合框关联的存储中,如何在从数据库获取记录时设置显示字段?目前,我们在extJs中没有像setDisplayField这样的方法,但我们有一个方法'setValue'来改变组合框中的值,这是不需要的。
我想在遇到数据库中的"id = d"时将显示字段更改为"娃娃"。
请帮忙。
谢谢
如果你真正想要的是一个setDisplayField
的方法,实际上它存在并且被称为setRawValue
。
但是,它本身是否足以解决您的问题是值得怀疑的。事实上,你可以用它来获得正确的显示,但你会失去你的价值......
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所建议的那样,将历史记录添加到组合的商店中确实可以解决您的问题,当且仅当您愿意让用户选择历史记录时。在我的理解中,情况并非如此,因为否则你一开始就不会有任何问题......
在检查了 combo 类的代码后,我认为实现所需内容的最佳方法是重写 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: true
创建存储,则会杀死组合框初始值。有关此内容的更多信息,请参阅其他问题。或者,您可以跳过全局修复,并将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);
}
}
});
最后,这是一个现场演示,其中包含大量示例,演示此 ux 适用于同步和异步存储和forceSelection
的所有组合......而setRawValue
没有。
我认为您可以通过创建一个 Ext.XTemplate,并将该模板设置为组合框上的 displayTpl 属性来做到这一点。然后,在模板中,您可以使用一种方法来测试应以不同方式显示的记录。
displayTpl 配置没有文档,但如果您查看 ComboBox 源代码并搜索 me.displayTpl,您可以看到它们只是创建一个默认的 displayTpl(如果不存在(。
您只需要在加载该记录后使用该记录store.add({id:'d',name:'doll'})
下面是一个示例,它不是您需要的,但显示了概念:
Ext.define('MyApp.store.Users', {
extend:'Ext.data.Store',
model:'MyApp.model.User',
listeners:{
load:function (store, recs) {
store.add({uid:'', name:''}); //adding empty record to enable deselection of assignment
}
}
});
- 如何在ExtJs4应用程序上为视图、存储和模型设置自定义文件夹名称
- 为数据库存储设置角度日期格式
- jQuery 设置和获取下拉列表和输入的本地存储数据
- 设置 HTML 自定义属性与在 ID 属性中存储信息
- 根据下拉值设置本地存储
- 如何在引导模式上设置本地存储
- 如何保存从单击this.nameClass动态设置的本地存储
- AngularJS设置本地存储(object json)
- 本地存储设置初始数据
- 将本地存储项设置为值'span'标签
- 如何读取存储在图像的数据src中的URL,并在另一个img控制器的src中设置该URL onclick
- 将对象设置为Chrome存储
- 设置存储在变量中的元素的属性
- 如何将javascript变量设置为php变量并将其存储在数据库中
- 如何将 HTML 的本地存储设置为整数而不是字符串
- 在量角器测试中从本地存储设置项目
- HTML5;绕过“;本地存储设置
- 不能与本地存储设置值
- 使用本地存储设置视图 MVC 中的值
- 如何 如果未定义,请将本地存储设置为 0