3.5.15.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);
}
}
- 启动应用程序服务。将生成如下所示的编辑界面: