Extjs combobox: скрыть выбранное значение из выпадающего списка
Я использую ExtJS 4 и ищу способ скрыть выбранное значение из выпадающего списка combo?
поэтому вместо этого ("Аляска" в настоящее время выбрана в combobox):
Я хочу, чтобы список значений выглядит так:
в моем случае combobox не редактируется (т. е. вы не можете ввести произвольное значение), я не думаю, что имеет смысл отображать выбранное значение два times: один раз в поле ввода и один раз в раскрывающемся списке. Я уже вижу, что выбрано, я хочу, чтобы выпадающий список только показывал мне другое параметры, которые я могу выбрать.
пока я не вижу простого способа сделать это. Вероятно, лучше всего начать с фильтрации combobox store, но combobox использует свои собственные фильтры для живого поиска.
кто-нибудь рассматривал эту проблему? Я пытаюсь сделать что-то странное? Я удивлен, что не смог ... найдите все связанные темы.
5 ответов
Я не думаю, что у вас есть много вариантов здесь... может быть, вы могли бы сделать что-то вроде этого:
Ext.define('Your.company.Combo', {
extend: 'Ext.form.field.ComboBox',
alias: 'widget.specialcombo',
/**
* @cfg {boolean} hideActive
* True to hide any selected record. Defaults to <tt>true</tt>.
*/
hideActive: true,
/**
* @private {Ext.data.Model[]} hideActive
* A Array of selected records.
*/
initComponent: function () {
this.selectedRecords = [];
this.callParent(arguments);
this.on('select', this.onSelectionChange, this);
},
/**
* @private onChangeSelection
* eventhandler selections
*/
onSelectionChange: function (me, recs) {
if(!me.hideActive)
return;
// write the current selected back to the store (you need to suspend autoSync if active)
me.store.add(me.selectedRecords);
// set the selected as new recordlist
me.selectedRecords = recs;
// remove the selected from the store
me.store.remove(recs);
}
});
этот пример совершенно непроверенные. Но поскольку магазин в основном привязан к BoundList, который не связан напрямую с textfield, это должно работать. Вы делаете своего рода кэширование здесь.
Я придумал другое решение, которое выглядит еще проще, и быстрое тестирование не показывает никаких побочных эффектов:
мы можем оставить логику Combobox нетронутой, но просто скрыть выбранный элемент через CSS:
.x-boundlist-selected {
display: none;
}
и вуаля, мы не видим выбранный товар! Не знаю, насколько это надежно в производственном коде, но все же стоит рассмотреть, Я думаю...
обновление. вот полное решение, если вы хотите контролировать это поведение через флаг конфигурации Combobox:
Ext.define('My.ComboBox', {
extend: 'Ext.form.field.ComboBox',
/**
* @cfg {Boolean} hideActive=true
* When true, hides the currently selected value from the dropdown list
*/
hideActive: true,
/**
* Internal method that creates the BoundList
*/
createPicker: function() {
var picker = this.callParent(arguments);
// honor the hideActive flag
if(this.hideActive) {
picker.addCls('x-boundlist-hideactive');
}
return picker;
}
});
где-то в вашем CSS:
.x-boundlist-hideactive .x-boundlist-selected {
display: none;
}
обновление 2. Нашел проблему с UI с моим подходом!
скрытие выбранного элемента из выпадающего списка вводит причуду навигации по клавиатуре: хотя элемент визуально скрыт, он все еще существует, и Ext выберет его при нажатии клавиш вверх/вниз. Визуально это означает, что ваш выбор исчезнет в какой-то момент, и вам придется нажать Вверх / вниз еще раз, чтобы вернуть его на следующий видимый элемент.
до сих пор я не смог найти простое решение для этого.
Лучше всего было бы изменить itemSelector
связанного списка (который является представление данных), установив его на что-то вроде .x-boundlist-item:not(.x-boundlist-selected)
таким образом, выбранный элемент не попадает в запрос.
хотя сам селектор работает, он не решает проблему, потому что представление выполняет этот запрос селектора перед любыми дополнительными классами (включая выбранный элемент class) применяется к элементам (это происходит в ВН.вид.AbstractView.refresh ().
кроме того, это решение вызывает смещение выпадающего списка список, когда он появляется над combobox!
у меня было ощущение, что мой подход слишком прост для безупречной работы:)
в итоге я использовал модифицированную версию решения @sra:
Ext.define('My.ComboBox', {
extend: 'Ext.form.field.ComboBox',
/**
* @cfg {Boolean} hideActive=true
* When true, hides the currently selected value from the dropdown list
*/
hideActive: true,
/**
* @private {Ext.data.Model[]} selectedRecords
* A Array of selected records, used when hideActive is true
*/
initComponent: function() {
this.selectedRecords = [];
this.callParent();
},
setValue: function(value, doSelect) {
var store = this.store;
if(this.hideActive) {
store.suspendEvents(false);
// write the current selected back to the store (you need to suspend autoSync if active)
// do this BEFORE callParent so the currently selected record would be found in the store
store.add(this.selectedRecords);
}
this.callParent(arguments);
if(this.hideActive) {
// set the selected as new recordlist
this.selectedRecords = this.valueModels;
// remove the selected from the store
store.remove(this.valueModels);
store.resumeEvents();
store.fireEvent('refresh', store);
}
return this;
}
});
логика "скрытия" такая же, только я выполняю ее в setValue
метод, чтобы убедиться, что он также работает при программном задании значения combo, включая случай, когда combobox инициализируется значением.
UPD кроме того, похоже store.add(this.selectedRecords);
называется до this.callParent(arguments);
, в противном случае combobox будет действовать странно, если мы попытаемся установить в одно и то же значение дважды (он просто не найдет активную запись в магазине, потому что мы ее удалили, поэтому она будет сброшена на пустую).
Я приостанавливаю события магазина, чтобы предотвратить некоторые причуды, вызванные combobox, пытающимся синхронизировать с его выпадающим списком в середине моих манипуляций с выбранными записями и вручную вызвать магазин 'refresh'
событие, когда я закончу, чтобы список в конечном итоге обновился. Это может повлиять на производительность, но пока я не знаю лучшего решения.
ExtJS 3 я написал этот ответ на основе других. Отлично работает для меня, его немного изменен от того, что вы ищете, хотя.
Name.space.name = new Ext.extend(Ext.form.ComboBox, {
type: 'all',
oldrec: null,
store: null,
constructor: function (config) {
var me = this;
if (config.type === 'all') {
me.store = AllConditionStore;
} else {
me.store = ?.?('RuleParameterType');
}
config = Ext.apply({
store: me.store,
valueField: 'id',
hideActive: true,
triggerAction: 'all',
lazyRender: true,
allowBlank: false,
mode: 'local',
displayField: 'text',
listeners: {
select: function (me, recs, index) {
if (me.oldrec !== null)
me.store.add(me.oldrec);
me.oldrec = recs;
// remove the selected from the store
me.store.remove(recs);
// redo store
}
}
}, config);
?.?.Parameter.superclass.constructor.call(this, config);
}
});
поэтому я использовал решение @sra, но с небольшой модификацией, чтобы добавить содержимое в нужное место ниже if(!me.hideActive)
:
if(me.selectedRecords[0]) {
me.store.insert(me.selectedRecords[0].index,me.selectedRecords);
}
таким образом, вы просто не добавлять их в боты. Я знаю, что это старый пост, но я надеюсь, что это поможет людям искать решение.