09.05.2016, 17:35
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Есть ли декларативный аналог метода relayEvents()?
Есть ли возможность декларативно описать таблицу пересылки событий?
Пример как я это делаю императивно:
initComponent: function() {
var me = this;
me.callParent(arguments);
me.relayEvents(me.down("settings-trolleylist"), "print-trolley-label-button-click");
},
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
|
|
09.05.2016, 19:50
|
|
Профессор
|
|
Регистрация: 21.05.2015
Сообщений: 321
|
|
Зачем это вообще делать? Используйте ViewController.
|
|
09.05.2016, 20:11
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Мне нужно из дочерних видов вытащить события в корневой вид.
Я в основном контроллере ловлю это событие:
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"?
.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Последний раз редактировалось khusamov, 09.05.2016 в 20:33.
|
|
09.05.2016, 20:22
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Если это делать в 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, чтобы просто настроить перенаправление событий и все.
.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Последний раз редактировалось khusamov, 09.05.2016 в 20:37.
|
|
09.05.2016, 20:28
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Или может так? Немного короче вышло:
init: function() {
var me = this;
var trolleyListView = me.getView().down("settings-trolleylist");
me.getView().relayEvents(trolleyListView, ["print-label-button-click"], "trolleylist-");
}
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
|
|
09.05.2016, 21:15
|
|
Профессор
|
|
Регистрация: 21.05.2015
Сообщений: 321
|
|
Я намекаю на то, что не нужно вообще использовать Ext.app.Controller для ловли событий в видах - для этого есть ViewController. И relayEvents в таком случае совершенно не нужно.
Глобальные контроллеры в новых приложениях нужно использовать только для глобальных вещей, которых в принципе немного: события с сервера, общая шина коммуникаций, глобальная конфигурация и т.д.
|
|
09.05.2016, 22:02
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
У меня в Ext.app.Controller организована печать на принтере (а именно прием заданий на печать, организация print-отчетов, подготовка данных к печати и т.п.). По-мойму вполне себе глобальная вещь. Зачем этот код плодить во всех видах?
Прием заданий я делаю путем ловли событий click из видов, в которых передается модель, которая затем поступает на вход отчета, и после обработки - в принтер. Это неправильно?
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Последний раз редактировалось khusamov, 09.05.2016 в 22:04.
|
|
09.05.2016, 22:34
|
|
Профессор
|
|
Регистрация: 21.05.2015
Сообщений: 321
|
|
Сообщение от khusamov
|
У меня в Ext.app.Controller организована печать на принтере (а именно прием заданий на печать, организация print-отчетов, подготовка данных к печати и т.п.). По-мойму вполне себе глобальная вещь. Зачем этот код плодить во всех видах?
|
Если печать у вас настолько сложна, что требует управления очередью и т.п., то в таком случае глобальный контроллер конечно же оправдан. В более простых случаях общий код можно включить в свой базовый класс ViewController, от которого потом наследовать ViewControllers для нужных видов.
Цитата:
|
Прием заданий я делаю путем ловли событий click из видов, в которых передается модель, которая затем поступает на вход отчета, и после обработки - в принтер. Это неправильно?
|
Технически такой подход допустим, и даже рекомендовался в версиях до 5.0, когда не было более удобных и менее проблематичных инструментов. Сейчас этот подход использовать настойчиво не рекомендуется, т.к. он чреват многими проблемами, для решения которых и предназначены ViewControllers.
В вашем случае я бы сделал так: 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 на выстреливание нужного события при нажатии на кнопку.
|
|
09.05.2016, 23:43
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Вообще-то я имел ввиду под моделью экземпляр класса Ext.data.Model, но это наверное не существенно.
Цитата:
|
...и возвращает код подтверждения/ошибки.
|
Это разве допустимо? А если на событие printrequest подпишутся два обработчика???
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
|
|
10.05.2016, 03:31
|
|
Профессор
|
|
Регистрация: 21.05.2015
Сообщений: 321
|
|
А почему нет? :) На самом деле, это нормальный способ синхронной (и двусторонней!) передачи информации через события, безотносительно типа коммуницирующих сторон. Можно конечно и по-другому делать: контроллер Foo стреляет событие "printrequest", контроллер Print обрабатывает и в ответ стреляет событие "printresponse", которое Foo ловит. Или даже передавать ссылку на контроллер Foo в аргументах события, и т.п... Но я бы не рекомендовал так делать, т.к. можно легко насоздавать себе проблем с рекурсией, циклами событий и прочими прелестями односторонней синхронности. А уж про тестирование таких вариантов я просто молчу - фактически это будет означать взаимную зависимость обоих контроллеров друг от друга.
Важно понимать, что в предложенном решении инициатором запроса является ViewController, а глобальный контроллер лишь пассивно реагирует на запрос. Такой подход даёт вполне чистое концептуальное разграничение между модулями программы, которую в дальнейшем проще поддерживать и тестировать.
А если на событие printrequest подпишутся два обработчика, то объект options по возврату будет содержать потенциально конфликтную информацию. Но этот случай тоже довольно легко отловить:
onPrintRequest: function(options) {
//<debug>
if (options.success != null) {
throw "Whoa there!";
}
//</debug>
}
На практике такое бывает довольно редко - мы же говорим о глобальных контроллерах, правда? Они ведь должны существовать в одном экземпляре, так ведь? И вы ведь это точно протестировали? ;)
|
|
|
|