Есть ли декларативный аналог метода relayEvents()?
Есть ли возможность декларативно описать таблицу пересылки событий?
Пример как я это делаю императивно: initComponent: function() { var me = this; me.callParent(arguments); me.relayEvents(me.down("settings-trolleylist"), "print-trolley-label-button-click"); }, |
Зачем это вообще делать? Используйте ViewController.
|
Мне нужно из дочерних видов вытащить события в корневой вид.
Я в основном контроллере ловлю это событие: Ext.define("Element.controller.Settings", { extend: "Ext.app.Controller", alias: "controller.app.settings", control: { "settings": { "trolleylist-print-label-button-click": "onTrolleyListPrintLabelButtonClick" } }, onTrolleyListPrintLabelButtonClick: function(trolleyListView, trolleyItem) { var me = this; var printer = me.getApplication().getController("Printer"); printer.print("trolleyitem", "barcode", trolleyItem); } }); Или вы намекаете что надо обойтись без relayEvents? И сделать в control селектор вида "settings > settings-trolleylist"? . |
Если это делать в ViewController, то так что-ли сделать?
control: { "settings-trolleylist": { "print-label-button-click": function() { var args = Ext.Array.slice(arguments); args.unshift("trolleylist-print-label-button-click"); this.getView().fireEvent.apply(this.getView(), args); } } }, Нагромождение какое-то вышло. Жаль что в контроллере нет конфига relayEvents, чтобы просто настроить перенаправление событий и все. . |
Или может так? Немного короче вышло:
init: function() { var me = this; var trolleyListView = me.getView().down("settings-trolleylist"); me.getView().relayEvents(trolleyListView, ["print-label-button-click"], "trolleylist-"); } |
Я намекаю на то, что не нужно вообще использовать Ext.app.Controller для ловли событий в видах - для этого есть ViewController. И relayEvents в таком случае совершенно не нужно.
Глобальные контроллеры в новых приложениях нужно использовать только для глобальных вещей, которых в принципе немного: события с сервера, общая шина коммуникаций, глобальная конфигурация и т.д. |
У меня в Ext.app.Controller организована печать на принтере (а именно прием заданий на печать, организация print-отчетов, подготовка данных к печати и т.п.). По-мойму вполне себе глобальная вещь. Зачем этот код плодить во всех видах?
Прием заданий я делаю путем ловли событий click из видов, в которых передается модель, которая затем поступает на вход отчета, и после обработки - в принтер. Это неправильно? |
Цитата:
Цитата:
В вашем случае я бы сделал так: ViewController ловит событие на дочерних компонентах и в свою очередь стреляет событие "printrequest" в контроллерном домене, передавая в аргументах объект со ссылкой на свою модель. Глобальный контроллер печати ловит события printrequest, берёт ссылку на модель, вытаскивает из неё нужные данные, ставит задание на печать и возвращает код подтверждения/ошибки. Ext.define('My.view.FooPanel', { extend: 'Ext.panel.Panel', controller: 'foocontroller', viewModel: { ... }, items: [{ ... }], buttons: [{ text: 'Печать', listeners: { click: 'onPrintButtonClick' } }] }); Ext.define('My.view.FooPanelController', { extend: 'Ext.app.ViewController', alias: 'controller.foocontroller', onPrintButtonClick: function() { var options = {}; options.viewModel = this.getViewModel(); // Стреляем событие в домене Controller this.fireEvent('printrequest', options); if (options.success) { ... } else { Ext.Msg.alert('Ошибка печати', options.errorMsg); } } }); Ext.define('My.controller.Print', { extend: 'Ext.app.Controller', listen: { controller: { '*': { printrequest: 'onPrintRequest' } } }, onPrintRequest: function(options) { // Здесь *категорически* не стоит сохранять ссылку на модель, // это практически на 100% приведёт к проблемам. // Вытащили данные и больше модель не трогаем. var data = this.getDataFromViewModel(options.viewModel); if (this.spoolPrintJob(data)) { options.success = true; } else { options.errorMsg = '...'; } } }); Такой подход позволяет отделить мух от котлет и в т.ч. очень помогает при тестировании. Вместо сложного комплекса итераций вам достаточно будет протестировать контроллер Print на принятие событий и правильную обработку данных, и ViewController на выстреливание нужного события при нажатии на кнопку. |
Вообще-то я имел ввиду под моделью экземпляр класса Ext.data.Model, но это наверное не существенно.
Цитата:
|
А почему нет? :) На самом деле, это нормальный способ синхронной (и двусторонней!) передачи информации через события, безотносительно типа коммуницирующих сторон. Можно конечно и по-другому делать: контроллер Foo стреляет событие "printrequest", контроллер Print обрабатывает и в ответ стреляет событие "printresponse", которое Foo ловит. Или даже передавать ссылку на контроллер Foo в аргументах события, и т.п... Но я бы не рекомендовал так делать, т.к. можно легко насоздавать себе проблем с рекурсией, циклами событий и прочими прелестями односторонней синхронности. А уж про тестирование таких вариантов я просто молчу - фактически это будет означать взаимную зависимость обоих контроллеров друг от друга.
Важно понимать, что в предложенном решении инициатором запроса является ViewController, а глобальный контроллер лишь пассивно реагирует на запрос. Такой подход даёт вполне чистое концептуальное разграничение между модулями программы, которую в дальнейшем проще поддерживать и тестировать. А если на событие printrequest подпишутся два обработчика, то объект options по возврату будет содержать потенциально конфликтную информацию. Но этот случай тоже довольно легко отловить: onPrintRequest: function(options) { //<debug> if (options.success != null) { throw "Whoa there!"; } //</debug> } На практике такое бывает довольно редко - мы же говорим о глобальных контроллерах, правда? Они ведь должны существовать в одном экземпляре, так ведь? И вы ведь это точно протестировали? ;) |
Часовой пояс GMT +3, время: 00:17. |