Vaadin: полезные доработки и наблюдения
Vaadin — компонентный UI фреймворк для создания веб-приложений на Java. Мы используем Vaadin в составе своей платформы CUBA на протяжении 4 лет и за это время накопили большой опыт работы с ним.
- Серверная модель программирования, не требующая применения JavaScript/HTML в прикладном коде
- Возможность создавать насыщенный AJAX UI
- Множество компонентов и сторонних аддонов
- Высокие требования к памяти сервера, поскольку все элементы пользовательского интерфейса и их данные хранятся в HTTP сессии
- Сложность расширения компонентов Vaadin и написания аддонов
Одной из особенностей корпоративного приложения является требование к изменению экранов интерфейса в зависимости от прав пользователя и состояния данных. Часто компоненты на форме размещаются по сетке с помощью GridLayout , и тогда при скрытии строк или столбцов в стандартном Vaadin остаются пустые места отступов для невидимых компонентов. Это поведение можно изменить, что потребует создания своего наследника GridLayout . Назовём его SuperGridLayout .
- SuperGridLayout — наследник серверной части GridLayout
- SuperGridLayoutConnector — коннектор для связи сервера с виджетом, наследник GridLayoutConnector
- 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
Я постарался показать самые простые решения, есть множество других доработок, но их рассмотрение может вылиться в отдельную статью.