3.5.13. 插件工厂

插件工厂机制扩展了标准组件的创建过程,允许在 FieldGroupTableDataGrid 中创建不同的编辑字段。这意味着应用程序组件或应用程序项目本身可以提供自定义策略,以创建非标准的组件或支持自定义数据类型。

该机制的入口点是 UiComponentsGenerator.generate(ComponentGenerationContext) 方法。其工作原理如下:

  • 尝试查找 ComponentGenerationStrategy 实现。如果找到至少一种策略,那么:
  • 根据 org.springframework.core.Ordered 接口遍历策略。

  • 返回第一个创建的非 null 组件。

ComponentGenerationStrategy 实现用于创建 UI 组件。项目可以包含任意数量的此类策略。

ComponentGenerationContext 是一个类,该类存储创建组件时可以使用的以下信息:

  • metaClass - 定义为其创建组件的实体。

  • property - 定义为其创建组件的实体属性。

  • datasource - 数据源。

  • optionsDatasource - 可用于显示选项列表的数据源。

  • valueSource - 可用于创建组件的值来源。

  • options - 可用于显示选项的选项对象。

  • xmlDescriptor - 在组件以声明的方式在 XML 描述中定义时,包含附加信息的 XML 描述。

  • componentClass - 要创建的组件的类型。例如,FieldGroupTableDataGrid

有两种内置组件策略:

  • DefaultComponentGenerationStrategy - 用于根据给定的 ComponentGenerationContext 对象创建组件。顺序值为 ComponentGenerationStrategy.LOWEST_PLATFORM_PRECEDENCE (1000)。

  • DataGridEditorComponentGenerationStrategy - 用于根据给定的 ComponentGenerationContext 对象为数据网格编辑器创建组件。顺序值为 ComponentGenerationStrategy.HIGHEST_PLATFORM_PRECEDENCE + 30 (130)。

以下示例展示如何替换为特定实体的某个属性 FieldGroup 组件的默认生成过程。

  1. import com.company.sales.entity.Order;
  2. import com.haulmont.chile.core.model.MetaClass;
  3. import com.haulmont.cuba.core.global.Metadata;
  4. import com.haulmont.cuba.gui.UiComponents;
  5. import com.haulmont.cuba.gui.components.*;
  6. import com.haulmont.cuba.gui.components.data.ValueSource;
  7. import org.springframework.core.Ordered;
  8. import javax.annotation.Nullable;
  9. import javax.inject.Inject;
  10. import java.sql.Date;
  11. @org.springframework.stereotype.Component(SalesComponentGenerationStrategy.NAME)
  12. public class SalesComponentGenerationStrategy implements ComponentGenerationStrategy, Ordered {
  13. public static final String NAME = "sales_SalesComponentGenerationStrategy";
  14. @Inject
  15. private UiComponents uiComponents;
  16. @Inject
  17. private Metadata metadata;
  18. @Nullable
  19. @Override
  20. public Component createComponent(ComponentGenerationContext context) {
  21. String property = context.getProperty();
  22. MetaClass orderMetaClass = metadata.getClassNN(Order.class);
  23. // Check the specific field of the Order entity
  24. // and that the component is created for the FieldGroup component
  25. if (orderMetaClass.equals(context.getMetaClass())
  26. && "date".equals(property)
  27. && context.getComponentClass() != null
  28. && FieldGroup.class.isAssignableFrom(context.getComponentClass())) {
  29. DatePicker<Date> datePicker = uiComponents.create(DatePicker.TYPE_DATE);
  30. ValueSource valueSource = context.getValueSource();
  31. if (valueSource != null) {
  32. //noinspection unchecked
  33. datePicker.setValueSource(valueSource);
  34. }
  35. return datePicker;
  36. }
  37. return null;
  38. }
  39. @Override
  40. public int getOrder() {
  41. return 50;
  42. }
  43. }


请注意,在更改返回的组件类型时,覆盖现有的生成策略可能会产生错误,因为界面控制器中的代码可能依赖于特定的组件类型。



例如,在使用上述策略的情况下,以下注入将产生异常:





  1. @Named("fieldGroup.date")
    private DateField<Date> dateField;






如果尝试打开此类界面,则会出现以下异常:





  1. IllegalArgumentException: Can not set com.haulmont.cuba.gui.components.DateField field com.company.sales.web.order.OrderEdit.dateField to com.haulmont.cuba.web.gui.components.WebDatePicker




以下示例展示如何为特定的 datatype 定义 ComponentGenerationStrategy

  1. import com.company.colordatatype.datatypes.ColorDatatype;
  2. import com.haulmont.chile.core.datatypes.Datatype;
  3. import com.haulmont.chile.core.model.MetaClass;
  4. import com.haulmont.chile.core.model.MetaPropertyPath;
  5. import com.haulmont.chile.core.model.Range;
  6. import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils;
  7. import com.haulmont.cuba.gui.UiComponents;
  8. import com.haulmont.cuba.gui.components.ColorPicker;
  9. import com.haulmont.cuba.gui.components.Component;
  10. import com.haulmont.cuba.gui.components.ComponentGenerationContext;
  11. import com.haulmont.cuba.gui.components.ComponentGenerationStrategy;
  12. import com.haulmont.cuba.gui.components.data.ValueSource;
  13. import org.springframework.core.annotation.Order;
  14. import javax.annotation.Nullable;
  15. import javax.inject.Inject;
  16. @Order(100)
  17. @org.springframework.stereotype.Component(ColorComponentGenerationStrategy.NAME)
  18. public class ColorComponentGenerationStrategy implements ComponentGenerationStrategy {
  19. public static final String NAME = "colordatatype_ColorComponentGenerationStrategy";
  20. @Inject
  21. private UiComponents uiComponents;
  22. @Nullable
  23. @Override
  24. public Component createComponent(ComponentGenerationContext context) {
  25. String property = context.getProperty();
  26. MetaPropertyPath mpp = resolveMetaPropertyPath(context.getMetaClass(), property);
  27. if (mpp != null) {
  28. Range mppRange = mpp.getRange();
  29. if (mppRange.isDatatype()
  30. && ((Datatype) mppRange.asDatatype()) instanceof ColorDatatype) {
  31. ColorPicker colorPicker = uiComponents.create(ColorPicker.class);
  32. colorPicker.setDefaultCaptionEnabled(true);
  33. ValueSource valueSource = context.getValueSource();
  34. if (valueSource != null) {
  35. //noinspection unchecked
  36. colorPicker.setValueSource(valueSource);
  37. }
  38. return colorPicker;
  39. }
  40. }
  41. return null;
  42. }
  43. protected MetaPropertyPath resolveMetaPropertyPath(MetaClass metaClass, String property) {
  44. MetaPropertyPath mpp = metaClass.getPropertyPath(property);
  45. if (mpp == null && DynamicAttributesUtils.isDynamicAttribute(property)) {
  46. mpp = DynamicAttributesUtils.getMetaPropertyPath(metaClass, property);
  47. }
  48. return mpp;
  49. }
  50. }