[ExtJs] Связанные комбобоксы


Возникла задача сделать так, чтобы при выборе группы студентов в одном комбобоксе, в другом комбобоксе процессор getlist возвращал записи относящиеся только к выбранной группе. Делюсь как решил эту задачу я, надеюсь кому нибудь пригодится =)




Решение

Вот так выглядит вызов xtype, где мы выбираем группу студентов. Вся соль в параметре listeners.

{
    xtype: 'portal-combo-group',
    id: config.id + '-group_id',
    name: 'group_id',
    anchor: '100%',
    hiddenName: 'group_id',
    fieldLabel: 'Группа',
    listeners: {
        select: {
            fn: function (combo, a, b) {
                var cmp = Ext.getCmp(config['id'] + '-schedule_id');
                if (!!cmp) {
                    cmp.getStore().baseParams['group_id'] = combo.getValue();
                    cmp.store.removeAll();
                    cmp.store.load();
                    cmp.reset();
                    cmp.setValue('');
                }
            },
            scope: this,
        }
    },
}
xtype поля даты:

{
    xtype: 'datefield',
    id: config.id + '-date',
    name: 'date',
    fieldLabel: 'Дата',
    anchor: '100%',
    format: 'd-m-Y',
    startDay: 1,
    listeners: {
        select: {
            fn: function (a,b) {
                var cmp = Ext.getCmp(config['id'] + '-schedule_id');
                if (!!cmp) {
                    cmp.getStore().baseParams['day'] = a.getValue().getDay();
                    cmp.store.removeAll();
                    cmp.store.load();
                    cmp.reset();
                    cmp.setValue('');
                }
            },
            scope: this,
        }
    }
}
Сам код комбы в которую подставлется значение вполне стандартный:

portal.combo.Schedule = function (config) {
    config = config || {};
    Ext.applyIf(config, {
        name: 'schedule_id',
        fieldLabel: config['name'] || 'schedule_id',
        hiddenName: config['name'] || 'schedule_id',
        displayField: 'day_time',
        emptyText: 'Выберите пару в расписании',
        valueField: 'id',
        fields: ['id', 'group_name','day','time_start','time_end','day_time'],
        url: portal.config['connector_url'],
        baseParams: {
            action: 'mgr/combo/getschedule',
            group_id: 0,
        },
        pageSize: 20,
        typeAhead: false,
        editable: true,
        minChars: 1,
        anchor: '100%',
        listEmptyText: '<div style="padding: 7px;">' + _('portal_combo_list_empty') + '</div>',
        tpl: new Ext.XTemplate('\
            <tpl for=".">\
                <div class="x-combo-list-item">\
                    <span>\
                        <small>({id})</small>\
                        <tpl if="group_name"> - {group_name}</tpl>\
                        <tpl if="day"> | {day}</tpl>\
                        <tpl if="time_start"> | {time_start}</tpl>\
                        <tpl if="time_end"> - {time_end}</tpl>\
                    </span>\
                </div>\
            </tpl>',
            {compiled: true}
        ),
    });
    portal.combo.Schedule.superclass.constructor.call(this, config);
};
Ext.extend(portal.combo.Schedule, MODx.combo.ComboBox);
Ext.reg('portal-combo-schedule', portal.combo.Schedule);
Фильтрация в процессоре:

public function prepareQueryBeforeCount(xPDOQuery $c)
    {
        $c->select('id,group_name,day,time_start,time_end');

        if ($query = trim($this->getProperty('query'))) {
            $c->where(array(
                'id:LIKE' => "{$query}%",
                'OR:group_name:LIKE' => "%{$query}%",
            ));
        }

        if ($group_id = (int)$this->getProperty('group_id')) {
            $c->where(array(
                'group_id' => "{$group_id}%",
            ));
        } else {
            $c->where(array(
                'id' => 0,
            ));
        }

        return $c;
    }

Функция которая заменяет дни недели на записи из лексиконов:

public function afterIteration(array $list)
    {
        foreach ($list as &$v) {
            $v['day_raw'] = $v['day'];
            $v['day'] = $this->modx->lexicon('week_day_' . $v['day']);
            $v['day_time'] = $v['day'] . ' / ' . $v['time_start'] . '-' . $v['time_end'];
        }
        return $list;
    }
Я использую эту штуку для выбора пары в расписании:

При выборе даты получаю записи только за конкретный день недели, дальше идет фильтрация по группе студентов. В итоге я получаю список пар для конкретной группы и в конкретный день недели, в зависимости от выбранной даты.

Спасибо @pavelgvozdb за помощь в этом вопросе и его modExtraLayout
16 августа 2017, 12:45    Николай Загумённов   
22    485 +14

Комментарии (7)

  1. Илья Уткин 16 августа 2017, 13:07 # +2
    Спасибо. Обязательно где-нибудь пригодится.
    1. Володя 16 августа 2017, 13:37 # +4
      id: config.id + '-group_id',
      желательно вообще не задавать, иначе будут проблемы при одновременном открытии нескольких окон, панелей и тд когда id дублируются.

      var cmp = Ext.getCmp(config['id'] + '-schedule_id');
      так тоже не есть хорошо, но когда нет других вариантов конечно можно)

      можно сделать так
      listeners: {
          select: {
              fn: function (r) {
                  this._handleChange();
              },
              scope: this
          }
      }
      
      //...
      
      _handleChange: function () {
          var f = this.fp.getForm();
      // получаем поля по имени
          var _field1 = f.findField('name_field1');
          var _field2 = f.findField('name_field1');
      
          _field2.baseParams['name_field1'] = _field1.getValue();
      
          // показываем пагинацию если нужно на комбике
          if (!!_field2.pageTb) {
              _field2.pageTb.show();
          }
          _field2.store.load();
      }
      
      1. Николай Загумённов 16 августа 2017, 23:46 # 0
        Интересно! Попробую!) Спасибо!
      2. Сергей Шлоков 16 августа 2017, 15:42 # +2
        Новое — это хорошо забытое старое.

        П.С. Маленький совет. Лучше обозвать топик «Связанные комбобоксы в ExtJs» или «Связанные списки в ExtJs». Так ближе к смыслу и легче будет потом найти пользователям.
        1. Николай Загумённов 16 августа 2017, 23:46 # 0
          Переименовал)
        2. Михаил 16 августа 2017, 18:23 # +2
          Кстати а чем modExtraLayout отличается от modExtra?
          1. Николай Загумённов 16 августа 2017, 23:45 # +3
            Многие штуки которые я часто использую там есть из коробки.
            Системные методы вынесены в отдельный класс tools.
            Окна create и update в админке сделаны так, что они в коде extjs все поля прописываются один раз, а не 2.
            … много всяких мелочей, все и не упомнишь =)
          Вы должны авторизоваться, чтобы оставлять комментарии.