4.7.4.1. Подключение аддона Vaadin
Рассмотрим пример использования компонента Stepper, доступного по адресу http://vaadin.com/addon/stepper. Данный компонент позволяет пошагово изменять значение текстового поля с помощью клавиатуры, колесика мыши и встроенных кнопок вверх/вниз.
Создайте новый проект в CUBA Studio и назовите его addon-demo
.
Для подключения аддона Vaadin проект должен иметь модуль web-toolkit. Создайте его, нажав на ссылку Create web toolkit module секции Project properties навигатора.
Далее нажмите на ссылку New UI component. Откроется окно создания визуального компонента UI component generation. В секции Component type выберите значение Vaadin add-on
.
Заполните следующие поля:
-
Add-on Maven dependency - в этом поле необходимо указать Maven-координаты аддона Vaadin для подключения его как зависимости к текущему проекту. Указание координат возможно в двух форматах:
-
XML, скопированный с сайта аддона (http://vaadin.com/addon/stepper):
<dependency> <groupId>org.vaadin.addons</groupId> <artifactId>stepper</artifactId> <version>2.2.2</version> </dependency>
-
Одной строкой в том виде, как вы добавляете зависимости в build.gradle:
org.vaadin.addons:stepper:2.2.2
-
-
Inherited widgetset - в этом поле необходимо указать имя виджетсета подключаемого аддона:
org.vaadin.risto.stepper.widgetset.StepperWidgetset
-
Integrate into generic UI - в данном примере флажок должен быть снят, т.к. мы не интегрируем компонент в универсальный интерфейс платформы.
Нажмите кнопку OK.
Если открыть проект в IDE, то можно увидеть, что Студия изменила два файла:
-
build.gradle. В модуле web появилась новая зависимость от аддона, содержащего компонент:
configure(webModule) { ... dependencies { ... compile("org.vaadin.addons:stepper:2.2.2") }
-
В файл
AppWidgetSet.gwt.xml
модуля web-toolkit проекта подключен виджетсет аддона после виджетсета платформы:<module> <inherits name="com.haulmont.cuba.web.toolkit.ui.WidgetSet" /> <inherits name="org.vaadin.risto.stepper.widgetset.StepperWidgetset" /> <set-property name="user.agent" value="safari" /> </module>
TipДля более быстрой сборки виджетов на время разработки вы можете установить свойство
user.agent
. В данном примере набор виджетов будет собираться только для браузеров, основанных на WebKit: Chrome, Safari, и т.д.
Компонент из аддона Vaadin подключен. Далее мы покажем как использовать его в экранах проекта.
-
Создаем новую сущность
Customer
с двумя полями:-
name
типа String -
score
типа Integer
-
-
Сгенерируем для новой сущности стандартные экраны. В диалоге генерации стандартных экранов убедитесь что значение поля In module -
Web Module
. Экраны, использующие компоненты Vaadin напрямую, должны располагаться в модуле web.TipНа самом деле экран может располагаться и в модуле gui, но тогда код, работающий с Vaadin компонентом, должен быть вынесен в отдельный компаньон.
-
Далее добавим компонент
stepper
на экран. Вы можете поместить его как в FieldGroup, так и вне ее. Рассмотрим оба способа.-
В XML-дескрипторе экрана редактирования
customer-edit.xml
для поляscore
компонентаfieldGroup
добавим атрибутcustom = "true"
:<?xml version="1.0" encoding="UTF-8" standalone="no"?> <window xmlns="http://schemas.haulmont.com/cuba/window.xsd" caption="msg://editCaption" class="com.company.addondemo.web.customer.CustomerEdit" datasource="customerDs" focusComponent="fieldGroup" messagesPack="com.company.addondemo.web.customer"> <dsContext> <datasource id="customerDs" class="com.company.addondemo.entity.Customer" view="_local"/> </dsContext> <layout expand="windowActions" spacing="true"> <fieldGroup id="fieldGroup" datasource="customerDs"> <column width="250px"> <field property="name"/> <field property="score" custom="true"/> </column> </fieldGroup> <frame id="windowActions" screen="editWindowActions"/> </layout> </window>
В контроллер экрана редактирования
CustomerEdit.java
добавим следующий код:package com.company.addondemo.web.customer; import com.haulmont.cuba.gui.components.AbstractEditor; import com.company.addondemo.entity.Customer; import com.haulmont.cuba.gui.components.Component; import com.haulmont.cuba.gui.components.FieldGroup; import com.haulmont.cuba.gui.components.VBoxLayout; import com.haulmont.cuba.gui.data.Datasource; import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; import com.haulmont.cuba.web.gui.components.WebComponentsHelper; import com.vaadin.ui.Layout; import org.vaadin.risto.stepper.IntStepper; import javax.inject.Inject; import java.util.Map; public class CustomerEdit extends AbstractEditor<Customer> { @Inject private ComponentsFactory componentsFactory; @Inject private FieldGroup fieldGroup; @Inject private Datasource<Customer> customerDs; private IntStepper stepper = new IntStepper(); @Override public void init(Map<String, Object> params) { fieldGroup.createField("score"); Component box = componentsFactory.createComponent(VBoxLayout.class); fieldGroup.getFieldNN("score").setComponent(box); Layout layout = (Layout) WebComponentsHelper.unwrap(box); layout.addComponent(stepper); stepper.setSizeFull(); stepper.addValueChangeListener(event -> customerDs.getItem().setValue("score", event.getProperty().getValue()) ); } @Override protected void initNewItem(Customer item) { item.setScore(0); } @Override protected void postInit() { stepper.setValue(getItem().getScore()); } }
Здесь в поле
stepper
создается экземпляр компонента, подключенного из аддона. В методеinit()
производится инициализация кастомного поляscore
. ЧерезComponentsFactory
создается экземпляр BoxLayout, затем из него с помощью WebComponentsHelper извлекается ссылка на Vaadin-контейнер, и в этот контейнер добавляется наш новый компонент.BoxLayout
возвращается для отображения в кастомном поле.Для связи компонента с данными, во-первых, в методе
postInit()
ему устанавливается текущее значение из редактируемогоCustomer
, а во-вторых, добавляется слушатель на изменение значения, который обновляет соответствующий атрибут сущности при изменении значения пользователем. -
Чтобы использовать новый компонент вне
FieldGroup
в произвольном месте экрана в XML-дескрипторе объявим контейнерscoreBox
и удалим полеscore
изfieldGroup
:<?xml version="1.0" encoding="UTF-8" standalone="no"?> <window xmlns="http://schemas.haulmont.com/cuba/window.xsd" caption="msg://editCaption" class="com.company.addondemo.web.customer.CustomerEdit" datasource="customerDs" focusComponent="fieldGroup" messagesPack="com.company.addondemo.web.customer"> <dsContext> <datasource id="customerDs" class="com.company.addondemo.entity.Customer" view="_local"/> </dsContext> <layout expand="windowActions" spacing="true"> <fieldGroup id="fieldGroup" datasource="customerDs"> <column width="250px"> <field property="name"/> </column> </fieldGroup> <hbox id="scoreBox" spacing="true"> <label value="Score" align="MIDDLE_LEFT"/> </hbox> <frame id="windowActions" screen="editWindowActions"/> </layout> </window>
В контроллере инжектируем контейнер, извлекаем ссылку на Vaadin-контейнер и добавляем в него компонент:
package com.company.addondemo.web.customer; import com.haulmont.cuba.gui.components.*; import com.company.addondemo.entity.Customer; import com.haulmont.cuba.gui.data.Datasource; import com.haulmont.cuba.web.gui.components.WebComponentsHelper; import com.vaadin.ui.Layout; import org.vaadin.risto.stepper.IntStepper; import javax.inject.Inject; import java.util.Map; public class CustomerEdit extends AbstractEditor<Customer> { @Inject private FieldGroup fieldGroup; @Inject private Datasource<Customer> customerDs; @Inject private BoxLayout scoreBox; private IntStepper stepper = new IntStepper(); @Override public void init(Map<String, Object> params) { Layout box = (Layout) WebComponentsHelper.unwrap(scoreBox); box.addComponent(stepper); stepper.setWidth("250px"); fieldGroup.addField(fieldGroup.createField("score")); stepper.addValueChangeListener(event -> customerDs.getItem().setValue("score", event.getProperty().getValue()) ); } @Override protected void initNewItem(Customer item) { item.setScore(0); } @Override protected void postInit() { stepper.setValue(getItem().getScore()); } }
Связь с данными выполняется здесь аналогично примеру с
FieldGroup
.
-
-
Для адаптации внешнего вида компонента создадим в проекте расширение темы. Для этого в Studio выполним команду Create theme extension секции Project properties навигатора. В списке тем для расширения выберем
halo
и нажмем кнопку Create. Затем откроем файлthemes/halo/com.company.application/halo-ext.scss
модуля web, и добавим в него следующий код:/* Define your theme modifications inside next mixin */ @mixin com_company_application-halo-ext { @include halo; /* Basic styles for stepper inner text box */ .stepper input[type="text"] { @include box-defaults; @include valo-textfield-style; &:focus { @include valo-textfield-focus-style; } } }
-
Запускаем сервер приложения. Экран редактирования должен выглядеть следующим образом: