Способ подключения сторонних компонентов Vaadin описан в Раздел 4.5.10.1, «Использование сторонних компонентов Vaadin».
Рассмотрим пример использования компонента Stepper, доступного по адресу http://vaadin.com/addon/stepper. Данный компонент позволяет пошагово изменять значение текстового поля с помощью клавиатуры, колесика мыши и встроенных кнопок вверх/вниз.
-
Предположим, что в проекте имеется сущность
Customerсо строковым атрибутом name. В модуле web создан экран редактированияcustomer-edit.xmlсо следующей компоновкой:<layout expand="windowActions" spacing="true"> <fieldGroup id="fieldGroup" datasource="customerDs"> <column width="250px"> <field id="name"/> </column> </fieldGroup> <iframe id="windowActions" screen="editWindowActions"/> </layout>Нам необходимо добавить атрибут
scoreтипаInteger, и обеспечить его пошаговое редактирование в данном экране. -
В CUBA Studio добавляем атрибут
scoreсущностиCustomer:@Column(name = "SCORE") protected Integer score; public void setScore(Integer score) { this.score = score; } public Integer getScore() { return score; }Генерируем скрипты обновления БД и запускаем обновление.
-
Выполняем команду секции Project properties навигатора Studio.
-
В build.gradle проекта добавляем зависимость модуля web от add-on, содержащего компонент:
configure(webModule) { ... dependencies { ... compile("org.vaadin.addons:stepper:2.1.2") } -
Пересоздаем проектные файлы IDE: меню .
-
В файл
AppWidgetSet.gwt.xmlмодуля web-toolkit проекта подключаем набор виджетов add-on после набора виджетов платформы:<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" />Для более быстрой сборки виджетов на время разработки можно установить свойство
user.agent. В данном примере набор виджетов будет собираться только для браузеров, основанных на WebKit: Chrome, Safari, и т.д. -
В XML-дескрипторе экрана редактирования
customer-edit.xmlдобавляем кастомное полеscoreв компонент fieldGroup:<fieldGroup id="fieldGroup" datasource="customerDs"> <column width="250px"> <field id="name"/> <field id="score" custom="true" caption="Score"/> </column> </fieldGroup> -
В контроллере экрана редактирования
CustomerEditдобавляем следующий код:public class CustomerEdit extends AbstractEditor<Customer> { @Inject private ComponentsFactory componentsFactory; @Inject private FieldGroup fieldGroup; private IntStepper stepper = new IntStepper(); @Override public void init(Map<String, Object> params) { fieldGroup.addCustomField("score", new FieldGroup.CustomFieldGenerator() { @Override public Component generateField(final Datasource datasource, final String propertyId) { Component box = componentsFactory.createComponent(BoxLayout.VBOX); com.vaadin.ui.Layout layout = WebComponentsHelper.unwrap(box); layout.addComponent(stepper); stepper.setSizeFull(); stepper.addValueChangeListener(new Property.ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { datasource.getItem().setValue(propertyId, event.getProperty().getValue()); } }); return box; } }); } @Override protected void postInit() { stepper.setValue(getItem().getScore()); } }Здесь в поле
stepperсоздается экземпляр компонента, подключенного из add-on. В методеinit()производится инициализация кастомного поляscore. ЧерезComponentsFactoryсоздается экземпляр BoxLayout, затем из него с помощью WebComponentsHelper извлекается ссылка на Vaadin-контейнер, и в этот контейнер добавляется наш новый компонент.BoxLayoutвозвращается для отображения в кастомном поле.Для связи компонента с данными во-первых, в методе
postInit()ему устанавливается текущее значение из редактируемогоCustomer, а во-вторых, добавляется слушатель на изменение значения, который обновляет соответствующий атрибут сущности при изменении значения пользователем. -
Новый компонент можно использовать и вне
FieldGroupв произвольном месте экрана. Для этого в XML-дескрипторе объявим контейнер:<hbox id="scoreBox" spacing="true"> <label value="Score"/> </hbox>В контроллере инжектируем контейнер, извлекаем ссылку на Vaadin-контейнер и добавляем в него компонент:
public class CustomerEdit extends AbstractEditor<Customer> { @Inject private BoxLayout scoreBox; private IntStepper stepper = new IntStepper(); @Override public void init(Map<String, Object> params) { com.vaadin.ui.Layout box = WebComponentsHelper.unwrap(scoreBox); box.addComponent(stepper); stepper.addValueChangeListener(new Property.ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { getItem().setValue("score", event.getProperty().getValue()); } }); } @Override protected void postInit() { stepper.setValue(getItem().getScore()); } }Связь с данными выполняется здесь аналогично примеру с
FieldGroup. -
Для адаптации внешнего вида компонента создадим в проекте расширение темы. Для этого в Studio выполним команду секции Project properties навигатора. Затем откроем файл
themes/havana/havana-ext.scssмодуля web, и добавим в него следующий код:@import "../havana/havana"; @mixin havana-ext { @include havana; /* Basic styles for stepper */ .v-stepper { /* Use box-sizing: border-box; for all browsers */ @include box-defaults; height: 25px; border: 0; /* Use theme fonts */ font-family: $theme_fonts; } /* Basic styles for inner text box */ .v-stepper input[type="text"] { /* Use box-sizing: border-box; for all browsers */ @include box-defaults; height: 25px; padding: 1px; outline: 0; margin: 0; /* Use border color from theme */ border: 1px solid $theme_fieldBorderColor; } /* Focused styles */ .v-stepper.v-stepper input[type="text"]:focus { /* Use focused border color from theme */ border-color: $theme_fieldFocusedBorderColor; /* hide default focus outline */ outline: 0; } /* Readonly styles */ .v-readonly.v-stepper input[type="text"], .v-readonly.v-stepper input[type="text"]:focus { /* Use readonly border color from theme */ border-color: $theme_fieldReadonlyBorderColor; } }

