Способ подключения сторонних компонентов 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; } }