Combobox в Ext JS
Функциональность выпадающих списков представлена классом Ext.form.ComboBox. Этот класс позволяет создавать списки, объекты которых загружаются как с сервера, либо могут быть объявлены непосредственно в коде:
var yourData = [ [1, 'JavaScript'], [2, 'PHP'], [3, 'RUBY'] ]; Ext.onReady(function(){ Ext.create('Ext.Panel', { width:500, height:120, items: [{ xtype: 'combobox', fieldLabel: 'Выберите язык', store: new Ext.data.SimpleStore({ id:0, fields: [ 'myId', //числовое значение - номер элемента 'myText' //текст ], data:yourData }), valueField:'myId', displayField:'myText', queryMode:'local' }], renderTo: Ext.getBody() }); });
Итак, выпадающий список имеет xtype combobox. Параметр fieldLabel
отображает метку-заголовок, который обозначает список.
Чтобы связать список с определенным набором данных, используется параметр store
. Этот параметр принимает объект хранилища - Ext.data.Store
(в данном случае взят подкласс Ext.data.SimpleStore, но могу использоваться и другие). Хранилище через свойство data
мы связываем с некоторым объектом
данных. Например, здесь объявлен в самом начале объект yourData, представляющий набор ключей-значений. Поле хранилища fields
показывает,
как будут отображаться данные из yourData.
Поле комбобокса valueField
содержит ключ, определенный в поле fields
хранилища, соответственно поле displayField
отображает связанное с ключом значение.
В конце мы задаем режим с помощью свойства queryMode
. Так как мы загружаем непосредственно из кода данные, то он имеет значение local
.
При загрузке с сервера надо установить режим remote
Загрузка данных с сервера
Предположим, у нас на сервере находится следующий файл с данными в формате json langData.json:
{ "success": true, "languages": [{ "name": "JavaScript", "ID": 1 }, { "name": "PHP", "ID": 2 }, { "name": "Ruby", "ID": 3 }] }
Затем у нам предстоит определить модель, связанную с хранилищем, а так же само хранилище. И связать хранилище с выпадающим списком, как в примере выше:
Ext.onReady(function(){ Ext.define('Language', { extend: 'Ext.data.Model', fields: [{ type: 'string', name: 'name' }, { type: 'int', name: 'ID' }] }); var store = Ext.create('Ext.data.Store', { model: 'Language', proxy: { type: 'ajax', url: 'langData.json', reader: { type: 'json', root: 'languages' } } }); Ext.create('Ext.Panel', { width:400, height:100, items: [{ xtype: 'combobox', fieldLabel: 'Выберите язык', autoSelect:true, store: store, valueField:'ID', displayField:'name', queryMode:'remote' }], renderTo: Ext.getBody() }); });
Во-первых, здесь мы создаем модель Language
, которая является фактически расширением класса Ext.data.Model. Для этой модели
определяем в параметре fields два поля: name с типом string и ID с типом int - как в нашем объекте json.
Второй шаг - создание хранилища, производного от Ext.data.Store. Для него мы указываем в поле model тип объектов - в данном случае это вышеопределенная модель. Затем в объекте proxy мы задаем файл, из которого модель будет наполняться данными в результате ajax-запроса и корневой узел объекта json на сервере, в котором будет идти поиск объектов.
На третьем этапе мы уже определяем сам комбобокс. В данном случае все как и в примере с загрузкой объектов из кода, только в качестве значения свойства
queryMode устанавливается значение remote
, а в качестве значения параметра store указывается ранее созданное хранилище.
Автозаполнение списка
Ext.form.ComboBox позволяет нам использовать возможности автозаполнения поля при вводе символов. Для этого надо установить свойство
typeAhead:true
:
Ext.onReady(function(){ var store = Ext.create('Ext.data.Store', { fields: ['name'], data:[ {name: 'JavaScript'}, {name: 'PHP'}, {name: 'RUBY'}, {name: 'Python'}, {name: 'C (ANSI)'}, {name: 'C++'}, {name: 'C#'} ] }); Ext.create('Ext.form.ComboBox', { fieldLabel: 'Выбрать язык', store: store, queryMode: 'local', displayField: 'name', valueField: 'name', typeAhead: true, typeAheadDelay: 100, hideTrigger: true, renderTo: Ext.getBody() }); });
Кроме свойства typeAhead в данном случае использовался параметр typeAheadDelay
, которое позволяет задать время задержки в миллисекундах
перед автозаполнением, а параметр hideTrigger: true
скрывает значок выбора из списка.
Рендеринг содержимого
Через свойство listConfig
класса Ext.form.ComboBox мы можем задать параметры рендеринга содержимого, задав шаблон заполнения html:
Ext.onReady(function(){ var store = Ext.create('Ext.data.Store', { fields: ['position', 'title', 'rate'], data:[{ position: 1, title: 'C', rate: '19.224' }, { position: 2, title: 'Java', rate: '17.455' }, { position: 3, title: 'Objective-C', rate: '10.383' }, { position: 4, title: 'C++', rate: '9.689' }, { position: 5, title: 'PHP', rate: '5.732' }] }); Ext.create('Ext.Panel', { title: 'Рейтинг TIOBE', width: 400, autoHeight: true, bodyPadding: 10, items: [{ xtype: 'combobox', fieldLabel: 'Выбрать язык', displayField: 'title', store: store, queryMode: 'local', anchor: '100%', listConfig: { getInnerTpl: function(){ return '<h3>{title} ({position})</h3>' + '<div class="rate" >Текущее значение: {rate}</div>'; } } }], renderTo: Ext.getBody() }); });
Что мы сделали в данном случае? В вышеприведенных примерах видно, что список отображает то свойство объекта, которое указано в параметре displayField
комбобокса. То есть если у нас displayField: 'name'
, то будет отображаться содержимое свойства name объекта.
В случае с рендерингом мы задаем параметр listConfig
. Свойства, заданные в этом параметре, применяются к объекту списка комбобокса
а именно к объекту Ext.view.BoundList. Класс BoundList имеет метод getInnerTpl
, который и возвращает значение для параметра displayField.
То есть определение параметра displayField: 'name'
будет фактически эквивалентно
getInnerTpl: function(displayField) { return '{' + displayField + '}'; },
где на место displayField подставляется name. Поэтому через метод getInnerTpl можно переопределить шаблон рендеринга содержимого в комбобоксе.