3.5.17.3.2. Подключение аддона Vaadin с интеграцией в Generic UI
В предыдущем разделе мы подключили в проект сторонний компонент Stepper. В данном разделе мы интегрируем его в универсальный пользовательский интерфейс CUBA, что даст разработчикам возможность использовать компонент декларативно в XML-дескрипторах экранов и связывать его с сущностями через Компоненты данных.
Чтобы интегрировать Stepper в Generic UI, необходимо создать следующие файлы:
-
Stepper
- интерфейс компонента в подкаталоге gui модуля web. -
WebStepper
- реализация компонента в подкаталоге gui модуля web. -
StepperLoader
- XML-загрузчик компонента в подкаталоге gui модуля web. -
ui-component.xsd
- описатель схемы XML для нового компонента. Если файл уже существует, то информацию о новом компоненте следует добавить в существующий файл.-
cuba-ui-component.xml
- файл регистрации загрузчика нового компонента в модуле web. Если файл уже существует, то информацию о новом компоненте следует добавить в существующий файл.
-
Откройте проект в IDE.
Создадим требуемые файлы и внесем в них необходимые изменения.
-
Создайте интерфейс
Stepper
в подкаталоге gui модуля web. Замените его содержимое на следующий код:package com.company.demo.web.gui.components; import com.haulmont.cuba.gui.components.Field; // note that Stepper should extend Field public interface Stepper extends Field<Integer> { String NAME = "stepper"; boolean isManualInputAllowed(); void setManualInputAllowed(boolean value); boolean isMouseWheelEnabled(); void setMouseWheelEnabled(boolean value); int getStepAmount(); void setStepAmount(int amount); int getMaxValue(); void setMaxValue(int maxValue); int getMinValue(); void setMinValue(int minValue); }
В качестве базового для нашего компонента выбран интерфейс
Field
. Это позволяет осуществить связь с данными (data binding), то есть отображать и редактировать значение некоторого атрибута сущности. -
Создайте класс
WebStepper
- реализации компонента в подкаталоге gui модуля web. Замените содержимое класса следующим кодом:package com.company.demo.web.gui.components; import com.haulmont.cuba.web.gui.components.WebV8AbstractField; import org.vaadin.risto.stepper.IntStepper; // note that WebStepper should extend WebV8AbstractField public class WebStepper extends WebV8AbstractField<IntStepper, Integer, Integer> implements Stepper { public WebStepper() { this.component = createComponent(); attachValueChangeListener(component); } private IntStepper createComponent() { return new IntStepper(); } @Override public boolean isManualInputAllowed() { return component.isManualInputAllowed(); } @Override public void setManualInputAllowed(boolean value) { component.setManualInputAllowed(value); } @Override public boolean isMouseWheelEnabled() { return component.isMouseWheelEnabled(); } @Override public void setMouseWheelEnabled(boolean value) { component.setMouseWheelEnabled(value); } @Override public int getStepAmount() { return component.getStepAmount(); } @Override public void setStepAmount(int amount) { component.setStepAmount(amount); } @Override public int getMaxValue() { return component.getMaxValue(); } @Override public void setMaxValue(int maxValue) { component.setMaxValue(maxValue); } @Override public int getMinValue() { return component.getMinValue(); } @Override public void setMinValue(int minValue) { component.setMinValue(minValue); } }
В качестве базового класса выбран
WebV8AbstractField
, который реализует логику интерфейсаField
. -
StepperLoader
в модуле web загружает компонент из его представления в XML.package com.company.demo.web.gui.xml.layout.loaders; import com.company.demo.web.gui.components.Stepper; import com.haulmont.cuba.gui.xml.layout.loaders.AbstractFieldLoader; public class StepperLoader extends AbstractFieldLoader<Stepper> { @Override public void createComponent() { resultComponent = factory.create(Stepper.class); loadId(resultComponent, element); } @Override public void loadComponent() { super.loadComponent(); String manualInput = element.attributeValue("manualInput"); if (manualInput != null) { resultComponent.setManualInputAllowed(Boolean.parseBoolean(manualInput)); } String mouseWheel = element.attributeValue("mouseWheel"); if (mouseWheel != null) { resultComponent.setMouseWheelEnabled(Boolean.parseBoolean(mouseWheel)); } String stepAmount = element.attributeValue("stepAmount"); if (stepAmount != null) { resultComponent.setStepAmount(Integer.parseInt(stepAmount)); } String maxValue = element.attributeValue("maxValue"); if (maxValue != null) { resultComponent.setMaxValue(Integer.parseInt(maxValue)); } String minValue = element.attributeValue("minValue"); if (minValue != null) { resultComponent.setMinValue(Integer.parseInt(minValue)); } } }
Логика загрузки базовых свойств компонента
Field
сосредоточена в классеAbstractFieldLoader
. Нам достаточно загрузить только специфические свойстваStepper
. -
В файле
cuba-ui-component.xml
, расположенном в корне модуля web, регистрируется новый компонент и его загрузчик. Замените содержимое файла следующим кодом:<?xml version="1.0" encoding="UTF-8" standalone="no"?> <components xmlns="http://schemas.haulmont.com/cuba/components.xsd"> <component> <name>stepper</name> <componentLoader>com.company.demo.web.gui.xml.layout.loaders.StepperLoader</componentLoader> <class>com.company.demo.web.gui.components.WebStepper</class> </component> </components>
-
Файл
ui-component.xsd
, расположенный в корне модуля web, это описатель XML схемы новых компонентов проекта. Добавьте элементstepper
и описание его атрибутов.<?xml version="1.0" encoding="UTF-8" standalone="no"?> <xs:schema xmlns="http://schemas.company.com/agd/0.1/ui-component.xsd" elementFormDefault="qualified" targetNamespace="http://schemas.company.com/agd/0.1/ui-component.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="stepper"> <xs:complexType> <xs:attribute name="id" type="xs:string"/> <xs:attribute name="caption" type="xs:string"/> <xs:attribute name="height" type="xs:string"/> <xs:attribute name="width" type="xs:string"/> <xs:attribute name="dataContainer" type="xs:string"/> <xs:attribute name="property" type="xs:string"/> <xs:attribute name="manualInput" type="xs:boolean"/> <xs:attribute name="mouseWheel" type="xs:boolean"/> <xs:attribute name="stepAmount" type="xs:int"/> <xs:attribute name="maxValue" type="xs:int"/> <xs:attribute name="minValue" type="xs:int"/> </xs:complexType> </xs:element> </xs:schema>
Далее рассмотрим, как добавить новый компонент на экран.
-
Либо удалите изменения, сделанные в предыдущем разделе, либо сгенерируйте для сущности стандартные экраны.
-
Далее добавим компонент
stepper
на экран. Вы можете добавить его как декларативно, так и программно. Рассмотрим оба способа.-
Декларативное использование компонента в XML-декскрипторе.
-
Откройте файл
customer-edit.xml
. -
Объявите новое пространство имен
xmlns:app="http://schemas.company.com/agd/0.1/ui-component.xsd"
-
Удалите поле
score
изform
. -
Добавьте компонент
stepper
на экран.
В результате XML-дескриптор редактора должен выглядеть так:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd" xmlns:app="http://schemas.company.com/agd/0.1/ui-component.xsd" caption="msg://editorCaption" focusComponent="form" messagesPack="com.company.demo.web.customer"> <data> <instance id="customerDc" class="com.company.demo.entity.Customer" view="_local"> <loader/> </instance> </data> <dialogMode height="600" width="800"/> <layout expand="editActions" spacing="true"> <form id="form" dataContainer="customerDc"> <column width="250px"> <textField id="nameField" property="name"/> <app:stepper id="stepper" dataContainer="customerDc" property="score" minValue="0" maxValue="20"/> </column> </form> <hbox id="editActions" spacing="true"> <button action="windowCommitAndClose"/> <button action="windowClose"/> </hbox> </layout> </window>
В данном примере компонент
stepper
подсоединен к атрибутуscore
сущностиCustomer
, экземпляр которой находится в источнике данныхcustomerDc
. -
-
Программное создание в контроллере Java.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd" caption="msg://editorCaption" focusComponent="form" messagesPack="com.company.demo.web.customer"> <data> <instance id="customerDc" class="com.company.demo.entity.Customer" view="_local"> <loader/> </instance> </data> <dialogMode height="600" width="800"/> <layout expand="editActions" spacing="true"> <form id="form" dataContainer="customerDc"> <column width="250px"> <textField id="nameField" property="name"/> </column> </form> <hbox id="editActions" spacing="true"> <button action="windowCommitAndClose"/> <button action="windowClose"/> </hbox> </layout> </window>
package com.company.demo.web.customer; import com.company.demo.entity.Customer; import com.company.demo.web.gui.components.Stepper; import com.haulmont.cuba.gui.UiComponents; import com.haulmont.cuba.gui.components.Form; import com.haulmont.cuba.gui.components.data.value.ContainerValueSource; import com.haulmont.cuba.gui.model.InstanceContainer; import com.haulmont.cuba.gui.screen.*; import javax.inject.Inject; @UiController("demo_Customer.edit") @UiDescriptor("customer-edit.xml") @EditedEntityContainer("customerDc") @LoadDataBeforeShow public class CustomerEdit extends StandardEditor<Customer> { @Inject private Form form; @Inject private InstanceContainer<Customer> customerDc; @Inject private UiComponents uiComponents; @Subscribe protected void onInit(InitEvent event) { Stepper stepper = uiComponents.create(Stepper.NAME); stepper.setValueSource(new ContainerValueSource<>(customerDc, "score")); stepper.setCaption("Score"); stepper.setWidthFull(); stepper.setMinValue(0); stepper.setMaxValue(20); form.add(stepper); } @Subscribe protected void onInitEntity(InitEntityEvent<Customer> event) { event.getEntity().setScore(0); } }
-
-
Запускаем сервер приложения. Экран редактирования должен выглядеть следующим образом: