. Vaadin: полезные доработки и наблюдения
Vaadin: полезные доработки и наблюдения

Vaadin: полезные доработки и наблюдения

Vaadin — компонентный UI фреймворк для создания веб-приложений на Java. Мы используем Vaadin в составе своей платформы CUBA на протяжении 4 лет и за это время накопили большой опыт работы с ним.

  • Серверная модель программирования, не требующая применения JavaScript/HTML в прикладном коде
  • Возможность создавать насыщенный AJAX UI
  • Множество компонентов и сторонних аддонов
  • Высокие требования к памяти сервера, поскольку все элементы пользовательского интерфейса и их данные хранятся в HTTP сессии
  • Сложность расширения компонентов Vaadin и написания аддонов
Пустое место в GridLayout

Одной из особенностей корпоративного приложения является требование к изменению экранов интерфейса в зависимости от прав пользователя и состояния данных. Часто компоненты на форме размещаются по сетке с помощью GridLayout , и тогда при скрытии строк или столбцов в стандартном Vaadin остаются пустые места отступов для невидимых компонентов. Это поведение можно изменить, что потребует создания своего наследника GridLayout . Назовём его SuperGridLayout .

  1. SuperGridLayout — наследник серверной части GridLayout
  2. SuperGridLayoutConnector — коннектор для связи сервера с виджетом, наследник GridLayoutConnector
  3. SuperGridLayoutWidget — сам виджет, наследник VGridLayout

Сам SuperGridLayout не содержит никакой логики:

В SuperGridLayoutConnector указано, что мы будем использовать виджет SuperGridLayoutWidget . Vaadin определяет это по типу возвращаемого значения метода getWidget() .

Ну и сам код виджета с исправлением для скрытия пропусков:

Теперь нужно добавить в свой проект сборку виджет сета с новым компонентом. Это подробно описано в документации Vaadin. Полный код можно посмотреть тут: https://github.com/Haulmont/vaadin-super-grid

Выделение по правому клику в дереве и таблице

По умолчанию Vaadin не выделяет запись, для которой мы открыли контекстное меню. И это поведение нельзя изменить без особых ухищрений. Добавим выделение по правому клику для дерева, для таблицы процесс похожий.

Назовём наше дерево SuperTree и заведём соответственно SuperTree , SuperTreeWidget и SuperTreeConnector . SuperTree — простой наследник Tree. А в SuperTreeWidget полностью скопируем код из VTree , в SuperTreeConnector — код из TreeConnector . Далее изменим код в SuperTreeConnector , чтобы он использовал виджет SuperTreeWiget и аннотацию @Connect(SuperTree.class) .

У нас получилась своя реализация клиентской части для серверного компонента Tree. В SuperTreeConnector заведём флаг contextMenuSelection и аксессоры для него. В методе updateFromUIDL при выставленном флаге будем сбрасывать для виджета флаг rendering = false и прерывать исполнение. Это необходимо, чтобы наше контекстное меню не было свёрнуто. Далее в SuperTreeWidget.TreeNode добавим в метод showContextMenu выделение узла, если он не выделен:

Теперь если пользователь будет кликать по узлу правой кнопкой мыши, наш узел будет обязательно выделен. Полный код тут: https://github.com/Haulmont/vaadin-super-tree

Горячие клавиши для полей ввода

Так повелось в API Vaadin, что горячие клавиши привязываются к объектам Panel , Window или UI . Это значит, что добавляя листнеры для горячих клавиш, к примеру, для поля, вы добавляете их к ближайшему по иерархии контейнеру-хранителю. Такое поведение приводит к тому, что для одинаковых клавиш в двух полях уже нужно писать хитрый код, ну и написание своих компонентов с горячими клавишами усложняется на порядок. Если же просто обернуть все дублирующиеся компоненты в панели, то мы усложним наш экран для браузера.

Решить эту задачу для таблиц и деревьев довольно сложно, рассмотрим простое решение на примере текстовых полей. Попробуем сделать свой SuperTextField с поиском по Enter и возможностью использовать несколько таких полей на экране.

В SuperTextField определим свой ActionManager , ответственный за горячие клавиши этого поля.

Теперь мы можем сделать сколько угодно полей SuperTextField с одними и теми же сочетаниями клавиш. Полный код тут: https://github.com/Haulmont/vaadin-super-textfield

Стили "-focus" для TabSheet, Table, CheckBox, Tree, MenuBar

В Vaadin для некоторых компонентов не хватает стилей различных состояний. Попробуем добавить селектор "-focus" для деревьев с фокусом.

Схема действий простая: заводим компонент FocusTree , FocusTreeConnector и FocusTreeWidget .

Добавляем стиль "-focus" в виджете:

Теперь остаётся только завести нужные CSS стили для компонента с селектором “v-tree-focus”. Пример тут: https://github.com/Haulmont/vaadin-focus-selector

Возможность отображать в ComboBox значение, которого нет в списке опций

В платформе CUBA стандартным является мягкое удаление объектов из БД. Удаленные объекты недоступны для использования, однако должны отображаться в составе других объектов, их использующих. То есть, если удалить некоторый объект Покупатель, то открыв Заказ, сделанный этим заказчиком, в поле выбора покупателя мы должны увидеть имя удаленного Покупателя, но в списке выбора он должен отсутствовать. Однако Vaadin не допускает проставлять в поле с выпадающим списком значение, которое отсутствует в опциях.

Эта возможность может быть просто реализована в контейнере опций. Достаточно, чтобы он для любого ключа сообщал (containsId), что такой элемент есть. Ограничение такого хака в том, что ключ и его элемент контейнера должны быть одним и тем же объектом.

Если вы выбираете данные для выпадающих списков вместе с простановкой значения, то вам достаточно использовать IndexedContainer или BeanContainer , содержащий и опции и значение. Когда же вы не управляете загрузкой данных для контейнера, может пригодиться такой хак. ( например SQLContainer или самописных источников данных).

О переходе на Vaadin 7

В Vaadin 7 изменилось многое, включая поддержку браузеров. Больше не поддерживается IE7, заявлена поддержка IE8+. Но вместе с тем появились большие проблемы с производительностью в IE 8. Коренным образом изменился процесс рендеринга компонентов, теперь он поэтапный и использует интенсивные расчёты на JavaScript. Это поведение никак нельзя изменить. Некоторые «сложные» экраны (таблица с 10ю колонками в 5 вложенных вертикальных боксах) в IE8 отрисовываются в 10-20 раз медленнее, чем в Chrome. При переходе или выборе Vaadin 7 учтите это. Мы решили эту проблему прямолинейно — поддерживаем в платформе Vaadin и 6, и 7 версии, а в проекте приложения можно выбрать, какую версию использовать.

dev.vaadin.com/ticket/12797 — Баг проверен, но активности по нему пока нет.

Также перед переходом убедитесь, что ваши аддоны будут работать в новой версии. Не все разработчики дополнений выпустили версии, совместимые с Vaadin 7.

  • Overlays: github.com/Haulmont/vaadin-overlays
  • Notifique: github.com/Haulmont/Notifique
  • AppletIntegration: github.com/Haulmont/AppletIntegration
Оговорки

Я постарался показать самые простые решения, есть множество других доработок, но их рассмотрение может вылиться в отдельную статью.

📎📎📎📎📎📎📎📎📎📎