3.5.17.3.2. 集成 Vaadin 组件到通用 UI 中
在前一节中,我们在项目中包含了第三方 Stepper 组件。在本节中,我们将它集成到 CUBA 通用 UI 中。这样就允许开发人员在界面 XML 描述中以声明方式使用组件,并通过数据组件将其绑定到数据模型实体。
为了在 CUBA 通用 UI 中集成 Stepper,需要创建以下文件:
-
Stepper
- 在 web 模块 gui 子文件夹的该组件接口。 -
WebStepper
- 在 web 模块 gui 子文件夹的该组件实现。 -
StepperLoader
- 在 web 模块 gui 子文件夹的组件 XML 加载器。 -
ui-component.xsd
- 一个新的组件 XML 结构定义。如果这个文件已经存在,在文件中添加关于此新组件的信息。 -
cuba-ui-component.xml
- 在 web 模块中注册新组件加载器的文件。如果该文件已存在,在文件中添加关于此新组件的信息。
在 IDE 中打开项目。
创建相应的文件,并添加必要的更改。
-
在 web 模块的 gui 子文件夹创建
Stepper
接口。用以下代码替换其内容: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
,用于显示和编辑实体属性。 -
创建
WebStepper
类 - web 模块的 gui 子文件夹中的组件实现。用以下代码替换其内容: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
接口的方法。 -
web 模块的 gui 子文件夹中的
StepperLoader
类从 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)); } } }
AbstractFieldLoader
类包含用于加载Field
组件的基本属性的代码。所以StepperLoader
只加载特定于Stepper
组件的属性。 -
web 模块中的
cuba-ui-component.xml
文件注册新组件及其加载器。用以下代码替换其内容:<?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>
-
web 模块中的
ui-component.xsd
文件包含自定义可视化组件的 XSD。添加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"
。 -
从
form
中删除score
字段。 -
将
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
组件与Customer
实体的score
属性相关联。该实体的实例由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); } }
-
-
启动应用程序服务。将生成如下所示的编辑界面: