Маска для элементов TabPanel
Всем привет!
Есть панель с вкладками, в каждой вкладке находится по таблице. Пытаюсь сделать маску на каждый item-таблицу, получилось только через событие afterrender, т к у GridPanel нет в конфигах маски: defaults: { listeners: { afterrender: function(grid) { grid.mask(); } } }, Однако есть интересная проблема. Т к у нас activeTab может быть только один, то и срабатывает событие лишь на активной вкладке. Переключаем вкладку — опять срабатывает на новой вкладке. Мне же нужно, чтобы маска применилась на всех элементах разом и при загрузке. У самой TabPanel нет события afterrender, а с added и перебором в цикле элементов-табов маска не применяется и вываливается с ошибкой: TypeError: target is undefined Так как же правильно применить маску? |
Правильно применить маску - это не применять маску. Да, именно так. Когда стор грузится, грид автоматически маскируется. Ну и не понятно насчет маскировки одновременно во всех табах. Зачем? Ведь активен, и соответственно виден только один таб за раз. Что происходит в остальных и так никто не узнает. А когда таб активизировался то и делайте в нем все что надо.
Или я что-то недопонял? |
Объясняю. У меня две таблицы с ассоцияциями (FK), при нажатии на строку 1й таблицы грузятся данные с фильтром по id этой записи во 2й таблице.
Однако по умолчанию 2я таблица при загрузке активна и если мы нажмем на кнопку обновления в pagingtoolbar'е, то получим ВСЕ записи, связанные и не связанные. К тому же, кнопки toptoolbar'а также все активны... Чтобы избежать ненужных нажатий пользователем и несвязанных данных, я маскирую таблицы. Можно, конечно, отключить саму TabPanel, но это выглядит менее эстетично, чем маска на Grid'ах. Да и вкладки остаются видимы и доступны с маской. |
Стало понятнее ) Мне кажется что маска тут неправильное решение. Поставьте подчиненному гриду disabled. Будут заблокированы тулбары и пейджер.
|
Как ни странно, решение с отключением самой таблицы делает неактивными и сами вкладки TabPanel. В итоге имеем идентичный вид, как если бы мы просто отключили сам TabPanel (монолитно серая отключенная панель).
|
Вот же хитрая бестия ) Ну попробуйте панель в панели: одна панель как сам таб, а в ней - гридпанель. Думаю должно помочь.
|
Честно сказать, глубоко не вчитывался, многабукаф. Fiddle было бы существенно нагляднее.
Однако имею сказать вот что: а) Не используйте afterrender в Classic toolkit ни за что и никогда. От слова "вообще". Это событие стреляет сразу после добавления свежесозданных элементов в DOM, до раскладки. Делать что-либо с DOM в этот момент - самый лучший путь к "тяжёлым и тормозным приложениям Ext JS". Используйте событие boxready, оно стреляет после раскладки.* б) Есть мнение, что конфиг maskElement может оказаться интересным. ц) По умолчанию карты в Tab panel рендерятся поодиночке после активации, сделано это экономии ради и производительности для. Конфиг deferredRender позволяет управлять этим поведением. * Кроме компонентов, использующих браузерную раскладку (liquidLayout: true). Таких компонентов в Classic Toolkit немного: кнопки и поля ввода, кроме текстовых полей с grow: true. Если liquidLayout == true, то событие boxready не стреляет и придётся использовать afterrender. Но лучше не надо, потому что принудительные браузерные раскладки убьют всю производительность на корню. |
nohuhu, Спасибо за разъяснения.
В общем, я заморочился и сделал Fiddle (1й раз в нем работал): https://fiddle.sencha.com/#fiddle/1mls По умолчанию оба зависимых Grid'а маскируются по событию boxready, но вкладки при этом доступны. По событию rowclick главного Grid маска снимается, но работает это только для активной вкладки! defferedRender: false мне не помог (в фидле есть эта строчка), а с maskElement не понял как работать. |
Fiddle вижу, спасибо. А как должно работать-то? При решении любой задачи всегда полезно знать ответ. :)
|
Ну вообще желательно такое поведение:
1. Маска накладывается на ВСЕ элементы TabPanel один раз. 2. При выборе строки 1го Grid все маски снимаются. Как сейчас происходит: 1. По событию boxready каждый раз накладывается маска на АКТИВНЫЙ элемент TabPanel. 2. При выборе строки 1го Grid снимается маска ТОЛЬКО У АКТИВНОГО элемента (событие rowclick), а при переключении на 2-ю вкладку маска остается, т к срабатывает boxready (п. 1). |
nohuhu, Посмотрите?
|
Sogl,
Прошу прощения, был в отпуске, а потом закрутился. Надеюсь, что ещё не поздно. Если я правильно понял ваше последнее сообщение, то вам нужно закрыть маской всю TabPanel изначально, до момента, пока не выбрана запись в Grid с левой стороны. В таком случае, почему бы не использовать привязку (binding) к выбранной записи в 1-м Grid, точно так же, как вы делаете во втором Grid? У каждого компонента есть метод setLoading, так что можно сделать вот такую привязку: bind: { loading: '{!customerGrid.selection.orders}' } Это не решит вопрос с изначальным маскированием TabPanel, т.к. bindings стреляют только в момент обновления. Для этого как раз подойдёт событие boxready на самой TabPanel: listeners: { boxready: function(panel) { panel.setLoading({ useMsg: false }); } } Я подправил и сохранил ваш fiddle, можете посмотреть вживую. Если что-то работает не так, как надо, уточните задачу. |
Не поздно =)
Цитата:
Попробовал перенести ваш код в секцию defaults, но маска с элементов так и не снимается. Еще так и не понял как работает вот такая запись и почему в ней стоит оператор логического НЕ: bind: { loading: '{!customerGrid.selection.orders}' } p.s. Кстати, Sencha Fiddle не показывает внесенные сторонние изменения в созданных fiddle? А то так сложно понять что было изменено. |
Цитата:
Цитата:
bind: { loading: '{!customerGrid.selection}' } Ассоциация customerGrid.selection публикуется компонентом customerGrid и содержит выделенную запись в customerGrid. С левой стороны у нас название "config", который нужно изменить, когда меняется ассоциация. "Config" в кавычках, потому что на самом деле у компонентов нет опции loading, которую можно было бы сконфигурировать, но есть метод setLoading, который можно вызвать. Binding всё равно, конфиг это или нет, оно дёрнет метод и скормит ему данные из ассоциации, когда эти данные изменяются. Дальше к оператору. Когда выделенных записей нет, нужна маска. Когда запись есть, маска не нужна - обратная логическая связь. Когда выделение есть, свойство customerGrid.selection содержит объект с выделенной записью. Когда выделения нет, это свойство равно null. Использованием логического НЕ мы убиваем двух зайцев: во-первых, инвертируем логическую связь в нужную нам сторону (есть запись - нет маски, и наоборот); во-вторых, приводим truthy объект "запись" к булевому значению true, или null к булевому false. Если бы нам нужна была прямая связь, то я бы использовал '{!!customerGrid.selection}', просто чтобы в метод setLoading передавалось всегда булевое значение, а не запись. Меньше потенциальных поводов для головной боли. Цитата:
|
nohuhu, Огромное спасибо! :thanks:
Теперь все работает как надо. Изначально я пытался маскировать каждый item в TabPanel и снимать маску со всех них по rowclick, а оказалось, что проще всего выставить maskElement: 'body' и не нужны никакие лишние телодвижения. Красота. Есть один непонятный момент. Как я понял из вашего описания и доки, вот эта запись: listeners: { boxready: function(panel) { panel.setLoading({ useMsg: false }); } }, выставляет маску без сообщения на ней (т к useMsg: false) перед загрузкой контейнера и после раскладки элементов DOM. Вы выше писали, что bind срабатывает только на обновление. По идее, без данного кода маска примениться не должна. Однако, без него вечно отображаться "Loading..." пока не кликнем на строку Grid, т е каким-то образом стандартная маска появляется. Почему? Фидл с этим моментом: https://fiddle.sencha.com/#fiddle/1mls Комментирую код c bind, возвращая boxready на место — все ОК, маска есть. Без этих 2х кусков кода никаких масок, что и должно быть. |
"Loading..." это сообщение по умолчанию, если вызвать просто setLoading(true). В какой-то момент стреляет binding и, поскольку выделенной записи нет, накладывает маску с сообщением. Мне показалось, что это выглядит довольно странно, поэтому я добавил обработчик boxready, чтобы снова установить маску, но уже без сообщения.
Вообще-то это скорее хак, но setLoading() не поддерживает конфигурацию маски на объекте, только в параметрах, поэтому приходится явно вызывать функцию, чтобы передать ей этот параметр. А если подумать, такая конфигурация была бы хорошей идеей. EXTJS-23472. :) |
Часовой пояс GMT +3, время: 12:38. |