Javascript-форум (https://javascript.ru/forum/)
-   ExtJS (https://javascript.ru/forum/extjs/)
-   -   Прослушивание событий между компонентами разных view (https://javascript.ru/forum/extjs/65528-proslushivanie-sobytijj-mezhdu-komponentami-raznykh-view.html)

Sogl 24.10.2016 04:42

Прослушивание событий между компонентами разных view
 
Всем привет!

Как обычно слушать события между контроллерами я уже знаю. Прописываем id для контроллера:
id: 'employees-window1',


Там же вызываем событие:
onCancelClick: function () {
    this.fireEvent('close');
},


В нужном контроллере слушаем события заданного контроллера (селектор по id):
listen : {
        controller : {
            '#employees-window1' : {
                close : 'onCancelClick'
            }
        }
    },


Это работает если у нас 2 контроллера объявлены. Но по идее нам 2й контроллер и не нужен, т к мы можем вызвать событие и на обработчике кнопки:
buttons: [{
    text: 'Сохранить',
    handler: 'onSaveClick'
}, {
    text: 'Отмена',
    handler: function() {
        this.fireEvent('close');
    }
}]


Но вот как слушать событие компонента? в данном случае формы внутри Window.

Нашел, что можно прописывать в `listen` еще и `component`:
http://docs.sencha.com/extjs/6.2.0/m...tml#cfg-listen

Как только не пробовал с заданием id для window, например, так:
listen : {
        component : {
            '#employees-window1 > button[text=Отмена]' : {
                close : 'onCancelClick'
            }
        }
    },


Не работает!
Вообще возможно так делать как я описал?

nohuhu 24.10.2016 21:02

Можно, но незачем. Используйте ViewController, они специально предназначены для отслеживания событий в своих view, включая иерархию. В данном случае вам нужен только один VC, в окне:

Ext.define('MyApp.view.WindowController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.windowcontroller',

    onSaveClick: function() {
        ...
    },

    onCancelClick: function() {
        ...
    }
});

Ext.define('MyApp.view.Window', {
    extend: 'Ext.window.Window',

    requires: [
        'MyApp.view.WindowController',
    ],

    controller: 'windowcontroller',

    items: [{
        xtype: 'form',
        ...
        buttons: [{
            text: 'Сохранить',
            handler: 'onSaveClick'
        }, {
            text: 'Отмена',
            handler: 'onCancelClick'
        }]
    }]
});

Sogl 25.10.2016 02:06

В том и дело, что я хочу один контроллер на оба View. Я уже писал о том, что хочу сделать тут, реализовал это с помощью событий. Сейчас главный ViewController слушает события другого (2й только делает fireEvent по кликам на кнопки), в итоге получаем единый this контекст и отсутствие проблем с постоянной выборкой view, viewmodel итп

Я мог бы обойтись без 2го viewController вообще, если бы знал каким образом слушать события определенного View. В этом и состоит мой вопрос: как это сделать? :)

XAPuTOH 25.10.2016 12:57

Можно во вью обьявлять метод контроллера который будет обрабатывать данное событие. Например у кнопки :
handler:'onbuttonclick'
. например сть главный вьюпорт и у него контроллер. в этом контроллере можно этот метод прописать.

Экcт будет искать его по всей иерархии контроллеров пока не найдет.
НО это не сработает внутри окон. они не в иерархии вьюпорта.

Есть ещё система глобальных событий экста.
например можно в каком нибудь месте сделать так:
Ext.GlobalEvents.fireEvent('EventName', .., .., ..)


А в контроллере:
Ext.on('EventName', this.method, this);


Но по логике так не правильно. Так как сильно затрудняет поиск что откуда взялось.

nohuhu 26.10.2016 03:55

Цитата:

Сообщение от Sogl (Сообщение 432885)
Я мог бы обойтись без 2го viewController вообще, если бы знал каким образом слушать события определенного View. В этом и состоит мой вопрос: как это сделать? :)

Тогда я не понимаю задачу. В первом сообщении вы же пишете:

Цитата:

Но вот как слушать событие компонента? в данном случае формы внутри Window.
Я говорю, что вам не нужно отдельные VC на окно и на форму. Объявите VC в окне, он будет слушать события из вложенных компонентов, в т.ч. формы.

Если вам нужно организовать общение между совершенно разрозненными компонентами, которые не входят в общую иерархию, то это другой случай. Можно стрелять события по домену controller из одного VC и слушать в другом VC, или пропускать их через брокера в виде глобального контроллера (или VC самого Viewport). Тут уже зависит от задачи и предпочтений.

Sogl 26.10.2016 07:49

Задача избавиться от 2го VC, который навешан на модальное окно с формой, потому что в нем ничего нет кроме 2-х вызовов fireEvent.
А в главном VC (грид) у меня получается слушать лишь другой VC (модального окна) через прописывание controller. При прописывании прослушки component почему-то не работает.

Иерархии тут, увы, нет, потому что если я добавляю форму как дочку от Грида, то появляется она поверх этого грида, а не viewport, как мне нужно.

Поэтому я добавляю окно так:
this.dialog = main.add(  //<--- main — это главный View

И обращаюсь к нему позже с помощью this.dialog.
Если прописать тупо `controller: ` у окна такой же, как и у Грида, то работать вся конструкция не станет, т к будет 2й экземпляр одного объекта и все привязанные ранее к this объекты уже не будут доступны.

nohuhu 28.10.2016 21:09

Теперь понял, спасибо. По поводу маскирования отвечу подробнее в другой ветке, но что касается ViewController, то лучше и проще добавить окно с формой как дочку grid.

Sogl 31.10.2016 01:58

Цитата:

но что касается ViewController, то лучше и проще добавить окно с формой как дочку grid.
Это да, но при таком подходе мы имеем 2 проблемы:
  1. Затеняется только сам Grid, а не viewport, причем при наличии прокрутки с примером основанным на admin-dashboard эта корявая "тень" еще и ездит туда-сюда.
  2. Центрируется окно опять-таки относительно координат Grid'а, причем относительно всей области прокрутки! Если у нас, к примеру, открыта панель разработчика и размер viewport'а уменьшен, то окна вообще не видно.

Сделал gif-ку с разными размерами браузера, чтобы было понятнее как это все выглядит:
http://i.imgur.com/ZHg9ak8.gifv

p.s. На синтетических примерах KitchenSink итп работает все отлично, т к там кроме грида с записями обычно ничего и нет ;)

nohuhu 03.11.2016 20:22

Да, я поиграл с вариантами и получается, что модальную маску никак не заставить работать нужным образом. Если окно является дочкой другого компонента, то ZIndexManager маскирует родительский компонент и это никак не обойти, поскольку зашито в приватных методах. :/

Поэтому тут два варианта: либо неправильная маскировка, либо "лишний" ViewController. Думайте сами, решайте сами.

kolka 04.11.2016 14:34

В нагрузку для этой темы есть интересная маленькая познавательная статейка - Declarative Listeners vs. Control


Часовой пояс GMT +3, время: 15:06.