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 接口。用以下代码替换其内容:
  1. package com.company.demo.web.gui.components;
  2. import com.haulmont.cuba.gui.components.Field;
  3. // note that Stepper should extend Field
  4. public interface Stepper extends Field<Integer> {
  5. String NAME = "stepper";
  6. boolean isManualInputAllowed();
  7. void setManualInputAllowed(boolean value);
  8. boolean isMouseWheelEnabled();
  9. void setMouseWheelEnabled(boolean value);
  10. int getStepAmount();
  11. void setStepAmount(int amount);
  12. int getMaxValue();
  13. void setMaxValue(int maxValue);
  14. int getMinValue();
  15. void setMinValue(int minValue);
  16. }

组件的基础接口是 Field,用于显示和编辑实体属性。

  • 创建 WebStepper 类 - web 模块的 gui 子文件夹中的组件实现。用以下代码替换其内容:
  1. package com.company.demo.web.gui.components;
  2. import com.haulmont.cuba.web.gui.components.WebV8AbstractField;
  3. import org.vaadin.risto.stepper.IntStepper;
  4. // note that WebStepper should extend WebV8AbstractField
  5. public class WebStepper extends WebV8AbstractField<IntStepper, Integer, Integer> implements Stepper {
  6. public WebStepper() {
  7. this.component = createComponent();
  8. attachValueChangeListener(component);
  9. }
  10. private IntStepper createComponent() {
  11. return new IntStepper();
  12. }
  13. @Override
  14. public boolean isManualInputAllowed() {
  15. return component.isManualInputAllowed();
  16. }
  17. @Override
  18. public void setManualInputAllowed(boolean value) {
  19. component.setManualInputAllowed(value);
  20. }
  21. @Override
  22. public boolean isMouseWheelEnabled() {
  23. return component.isMouseWheelEnabled();
  24. }
  25. @Override
  26. public void setMouseWheelEnabled(boolean value) {
  27. component.setMouseWheelEnabled(value);
  28. }
  29. @Override
  30. public int getStepAmount() {
  31. return component.getStepAmount();
  32. }
  33. @Override
  34. public void setStepAmount(int amount) {
  35. component.setStepAmount(amount);
  36. }
  37. @Override
  38. public int getMaxValue() {
  39. return component.getMaxValue();
  40. }
  41. @Override
  42. public void setMaxValue(int maxValue) {
  43. component.setMaxValue(maxValue);
  44. }
  45. @Override
  46. public int getMinValue() {
  47. return component.getMinValue();
  48. }
  49. @Override
  50. public void setMinValue(int minValue) {
  51. component.setMinValue(minValue);
  52. }
  53. }

所选择的基类是 WebV8AbstractField,其实现了 Field 接口的方法。

  • web 模块的 gui 子文件夹中的 StepperLoader 类从 XML 描述中加载组件。
  1. package com.company.demo.web.gui.xml.layout.loaders;
  2. import com.company.demo.web.gui.components.Stepper;
  3. import com.haulmont.cuba.gui.xml.layout.loaders.AbstractFieldLoader;
  4. public class StepperLoader extends AbstractFieldLoader<Stepper> {
  5. @Override
  6. public void createComponent() {
  7. resultComponent = factory.create(Stepper.class);
  8. loadId(resultComponent, element);
  9. }
  10. @Override
  11. public void loadComponent() {
  12. super.loadComponent();
  13. String manualInput = element.attributeValue("manualInput");
  14. if (manualInput != null) {
  15. resultComponent.setManualInputAllowed(Boolean.parseBoolean(manualInput));
  16. }
  17. String mouseWheel = element.attributeValue("mouseWheel");
  18. if (mouseWheel != null) {
  19. resultComponent.setMouseWheelEnabled(Boolean.parseBoolean(mouseWheel));
  20. }
  21. String stepAmount = element.attributeValue("stepAmount");
  22. if (stepAmount != null) {
  23. resultComponent.setStepAmount(Integer.parseInt(stepAmount));
  24. }
  25. String maxValue = element.attributeValue("maxValue");
  26. if (maxValue != null) {
  27. resultComponent.setMaxValue(Integer.parseInt(maxValue));
  28. }
  29. String minValue = element.attributeValue("minValue");
  30. if (minValue != null) {
  31. resultComponent.setMinValue(Integer.parseInt(minValue));
  32. }
  33. }
  34. }

AbstractFieldLoader 类包含用于加载 Field 组件的基本属性的代码。所以 StepperLoader 只加载特定于 Stepper 组件的属性。

  • web 模块中的 cuba-ui-component.xml 文件注册新组件及其加载器。用以下代码替换其内容:
  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <components xmlns="http://schemas.haulmont.com/cuba/components.xsd">
  3. <component>
  4. <name>stepper</name>
  5. <componentLoader>com.company.demo.web.gui.xml.layout.loaders.StepperLoader</componentLoader>
  6. <class>com.company.demo.web.gui.components.WebStepper</class>
  7. </component>
  8. </components>
  • web 模块中的 ui-component.xsd 文件包含自定义可视化组件的 XSD。添加 stepper 元素及其属性定义。
  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <xs:schema xmlns="http://schemas.company.com/agd/0.1/ui-component.xsd"
  3. elementFormDefault="qualified"
  4. targetNamespace="http://schemas.company.com/agd/0.1/ui-component.xsd"
  5. xmlns:xs="http://www.w3.org/2001/XMLSchema">
  6. <xs:element name="stepper">
  7. <xs:complexType>
  8. <xs:attribute name="id" type="xs:string"/>
  9. <xs:attribute name="caption" type="xs:string"/>
  10. <xs:attribute name="height" type="xs:string"/>
  11. <xs:attribute name="width" type="xs:string"/>
  12. <xs:attribute name="dataContainer" type="xs:string"/>
  13. <xs:attribute name="property" type="xs:string"/>
  14. <xs:attribute name="manualInput" type="xs:boolean"/>
  15. <xs:attribute name="mouseWheel" type="xs:boolean"/>
  16. <xs:attribute name="stepAmount" type="xs:int"/>
  17. <xs:attribute name="maxValue" type="xs:int"/>
  18. <xs:attribute name="minValue" type="xs:int"/>
  19. </xs:complexType>
  20. </xs:element>
  21. </xs:schema>

我们来看一下如何将新组件添加到界面。

  • 可以删除前一章节的改动或者为实体生成编辑界面。

  • stepper 组件添加到编辑界面。可以使用声明式的方式或者编程的方式进行添加。我们分别看看这两种方法。

  • 在 XML 描述中声明式的使用该组件。
  1. -

打开 customer-edit.xml 文件。

  1. -

定义新的命名空间 xmlns:app="http://schemas.company.com/agd/0.1/ui-component.xsd&#34;

  1. -

form 中删除 score 字段。

  1. -

stepper 组件添加到界面上。

这时,界面 XML 描述应如下所示:

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
  3. xmlns:app="http://schemas.company.com/agd/0.1/ui-component.xsd"
  4. caption="msg://editorCaption"
  5. focusComponent="form"
  6. messagesPack="com.company.demo.web.customer">
  7. <data>
  8. <instance id="customerDc"
  9. class="com.company.demo.entity.Customer"
  10. view="_local">
  11. <loader/>
  12. </instance>
  13. </data>
  14. <dialogMode height="600"
  15. width="800"/>
  16. <layout expand="editActions" spacing="true">
  17. <form id="form" dataContainer="customerDc">
  18. <column width="250px">
  19. <textField id="nameField" property="name"/>
  20. <app:stepper id="stepper"
  21. dataContainer="customerDc" property="score"
  22. minValue="0" maxValue="20"/>
  23. </column>
  24. </form>
  25. <hbox id="editActions" spacing="true">
  26. <button action="windowCommitAndClose"/>
  27. <button action="windowClose"/>
  28. </hbox>
  29. </layout>
  30. </window>

在上面的例子中,stepper 组件与 Customer 实体的 score 属性相关联。该实体的实例由 customerDc 实例容器管理。

  • 在 Java 控制器中以编程的方式创建组件。
  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
  3. caption="msg://editorCaption"
  4. focusComponent="form"
  5. messagesPack="com.company.demo.web.customer">
  6. <data>
  7. <instance id="customerDc"
  8. class="com.company.demo.entity.Customer"
  9. view="_local">
  10. <loader/>
  11. </instance>
  12. </data>
  13. <dialogMode height="600"
  14. width="800"/>
  15. <layout expand="editActions" spacing="true">
  16. <form id="form" dataContainer="customerDc">
  17. <column width="250px">
  18. <textField id="nameField" property="name"/>
  19. </column>
  20. </form>
  21. <hbox id="editActions" spacing="true">
  22. <button action="windowCommitAndClose"/>
  23. <button action="windowClose"/>
  24. </hbox>
  25. </layout>
  26. </window>
  1. package com.company.demo.web.customer;
  2. import com.company.demo.entity.Customer;
  3. import com.company.demo.web.gui.components.Stepper;
  4. import com.haulmont.cuba.gui.UiComponents;
  5. import com.haulmont.cuba.gui.components.Form;
  6. import com.haulmont.cuba.gui.components.data.value.ContainerValueSource;
  7. import com.haulmont.cuba.gui.model.InstanceContainer;
  8. import com.haulmont.cuba.gui.screen.*;
  9. import javax.inject.Inject;
  10. @UiController("demo_Customer.edit")
  11. @UiDescriptor("customer-edit.xml")
  12. @EditedEntityContainer("customerDc")
  13. @LoadDataBeforeShow
  14. public class CustomerEdit extends StandardEditor<Customer> {
  15. @Inject
  16. private Form form;
  17. @Inject
  18. private InstanceContainer<Customer> customerDc;
  19. @Inject
  20. private UiComponents uiComponents;
  21. @Subscribe
  22. protected void onInit(InitEvent event) {
  23. Stepper stepper = uiComponents.create(Stepper.NAME);
  24. stepper.setValueSource(new ContainerValueSource<>(customerDc, "score"));
  25. stepper.setCaption("Score");
  26. stepper.setWidthFull();
  27. stepper.setMinValue(0);
  28. stepper.setMaxValue(20);
  29. form.add(stepper);
  30. }
  31. @Subscribe
  32. protected void onInitEntity(InitEntityEvent<Customer> event) {
  33. event.getEntity().setScore(0);
  34. }
  35. }
  • 启动应用程序服务。将生成如下所示的编辑界面:

customer edit result