[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, 09:45
23
904
+14

Комментарии: 7

Илья Уткин
16 августа 2017, 13:07
+2
Спасибо. Обязательно где-нибудь пригодится.
Володя
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();
}
Сергей Шлоков
16 августа 2017, 15:42
+2
Новое — это хорошо забытое старое.

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