
Для начала представим гипотетическую ситуацию, в которой у нас на сайте есть некие «Предметы» и с каждым предметом можно проводить некие «Операции». Попробуем связать Предметы и Операции.
После установки CustomExtra включим 2 вкладки — у предметов 0 числовых, строковых и текстовых полей, а у операций — 1 дополнительное числовое поле (в него мы будем сохранять id предмета)

Добавляем ComboBox
Для начала изменим тип поля у операций на выпадающий список. Для этого переходим в файл, ответственный за построение окон — assets/components/customextra/js/mgr/widgets/operations.windows.js, находим часть, которая перебирает числовые поля и добавляем условие, чтобы конкретное поле id1 имело особый xtype:
... ,items: [{ // У первого поля особый тип xtype: i == 1 ? 'customextra-combo-items' : 'textfield', fieldLabel: _('customextra_operation_id' + i), name: 'id' + i, id: config.id + '-id' + i, anchor: '99%', allowBlank: true, ]} ...
Добавить условие надо в 2 места, так как у нас есть окно создания операции и окно редактирования операции. Но, если по задумке так надо, эти окна могут быть разными. Например, из окна редактирования операции это поле можно вообще убрать, тогда не получится случайно изменить связь с предметом.
Теперь, в конце файла добавляем такой код (тут создаётся особый тип поля, который будет получать предметы и подставлять их в выпадающий список):
customExtra.combo.items = function(config) { config = config || {}; Ext.applyIf(config,{ name: 'id1' ,fieldLabel: 'Предмет' ,hiddenName: 'id1' ,displayField: 'name' ,valueField: 'id' ,anchor: '99%' ,fields: ['id','name'] ,pageSize: 20 // Если будете использовать не в CustomExtra, не забудьте проверить правильность // написание параметра connector_url - у вас он может отличатсья. ,url: customExtra.config.connector_url ,editable: true ,allowBlank: true ,emptyText: 'Выберите Предмет' ,baseParams: { action: 'mgr/item/getlist' ,combo: 1 } ,tpl: new Ext.XTemplate( '<tpl for=".">\ <div class="x-combo-list-item">\ <strong>{name}</strong> <sup>({id})</sup>\ </div>\ </tpl>' ,{compiled: true} ) }); customExtra.combo.items.superclass.constructor.call(this,config); }; Ext.extend(customExtra.combo.items,MODx.combo.ComboBox); Ext.reg('customextra-combo-items',customExtra.combo.items);
Теперь, если вы обновите страницу CustomExtra (Ctrl + R), окно создания операций будет выглядеть так:

Однако в самой табличке будет отображаться id, а не называние предмета.

За формирование списка операций отвечает процессор core/components/customextra/processors/mgr/operation/getlist.class.php
Добавим в него выборку предметов и подстановку в ячейку нужного значения:
public function prepareQueryBeforeCount(xPDOQuery $c) { // Добавляем в выборку предметы $c->leftJoin('customExtraItem', 'customExtraItem', '`customExtraItem`.`id` = `'.$this->classKey.'`.`id1`'); $c->select($this->modx->getSelectColumns($this->classKey, $this->classKey)); $c->select('`customExtraItem`.`name` as `item_name`'); $c->groupby($this->classKey . '.id'); // конец $query = trim($this->getProperty('query')); if ($query) { $c->where(array( 'name:LIKE' => "%{$query}%", 'OR:description:LIKE' => "%{$query}%", )); } return $c; }
И в файле, ответственном за построение таблицы, укажем, что показывать надо имя, а не id
getFields: function (config) { // Добавляем поле item_name в список var fields = ['id', 'name', 'description', 'item_name', 'active', 'actions', 'deleted', 'published', 'paid', 'new', 'hit', 'favorite']; //... }, getColumns: function (config) { // ... // А в колонке вместо первого дополнительного id показываем имя for(var i = 1; i < ids; i++) { columns.push({ header: _('customextra_operation_id' + i), dataIndex: i == 1 ? 'item_name' : 'id' + i, sortable: true, width: partWidth, }); } // ... },
Теперь и в табличке показывается название предмета

Выводим вложенную табличку в окне
Чтобы вывести табличку нужно добавить такой код в метод окна редактирования (перед return):
Ext.extend(customExtra.window.UpdateItem, MODx.Window, { getFields: function (config) { // ... fields.push({ xtype: 'customextra-grid-operations', fieldLabel: _('customextra_operations'), id: config.id + '-operations', record: config.record, anchor: '99%' }); return fields; }, // ... });
Табличка выводится, но она выводится вся, а нам нужен список только связанных операций. Для этого добавим 2 строчки в файл, отвечающий за табличку операций assets/components/customextra/js/mgr/widgets/operations.grid.js
customExtra.grid.Operations = function (config) { config = config || {}; // Чтобы табличка отдельно работала, создадим нулевой объект config.record = config.record || {object: {id: 0}} if (!config.id) { config.id = 'customextra-grid-operations'; } Ext.applyIf(config, { // ... baseParams: { action: 'mgr/operation/getlist' // В процессор будем передавать id предмета ,item_id: config.record.object.id },
А в процессор добавим выборку по id предмета:
public function prepareQueryBeforeCount(xPDOQuery $c) { // Добавляем в выборку предметы $c->leftJoin('customExtraItem', 'customExtraItem', '`customExtraItem`.`id` = `'.$this->classKey.'`.`id1`'); $c->select($this->modx->getSelectColumns($this->classKey, $this->classKey)); $c->select('`customExtraItem`.`name` as `item_name`'); $c->groupby($this->classKey . '.id'); // конец // Добавляем выборку по id предмета $item_id = trim($this->getProperty('item_id')); if ($item_id) { $c->where(array( 'id1' => $item_id )); } // конец $query = trim($this->getProperty('query')); if ($query) { $c->where(array( 'name:LIKE' => "%{$query}%", 'OR:description:LIKE' => "%{$query}%", )); } return $c; }
Та-дам!

Операции можно создавать, редактировать, удалять. Даже поиск работает. Но есть неудобство — при клике на кнопку «Создать операцию», поле «Предмет» будет пустым. Хочется, чтобы там уже был указан текущий предмет. Для этого добавим id в список устанавливаемых значений в файле operations.grid.js:
createOperation: function (btn, e) { // ... w.setValues({active: true, published: true, id1: this.record.object.id}); w.show(e.target); },
Вот теперь всё удобно и красиво

Шпаргалка
Итак, чтобы добавить свой combobox к полю, нужно:
- У нужного поля указать свой тип xtype
- Описать этот xtype в том же файле
- В процессор getlist добавить выборку нужных объектов
- В табличке (grid) у нужной ячейки указать нужное поле для отображения
- Добавить эту таблицу в список полей окна
- В самой таблице добавить передачу нужного id (config.record.object.id)
- В процессор getlist добавить выборку по соответствующему полю
- Для вложенного окна создания указать значение по умолчанию
Источник: https://modx.pro/howto/9135-object-relations-in-customextra/
0 комментариев