可插拔组件工厂

可插拔组件工厂机制扩展了标准组件的创建过程,支持在 FormTableDataGrid 中创建不同的编辑组件。也就是说,应用程序组件或你的应用程序项目本身可以提供自定义策略,以创建非标准的组件或支持自定义数据类型。

该机制的入口点是 UiComponentsGenerator.generate(ComponentGenerationContext) 方法。首先,尝试找到 ComponentGenerationStrategy(组件生成策略) 的实现;如果找到至少一种策略,然后会根据 org.springframework.core.Ordered 接口定义的顺序遍历这些策略;最后,返回创建的第一个非 null 组件。

ComponentGenerationStrategy 的实现用于创建 UI 组件。一个项目可以包含任意个这种策略。

创建组件时,ComponentGenerationContext 类存储可以使用的信息:

  • metaClass - 实体类,指定为该实体创建组件。

  • property - 实体属性,指定为该属性创建组件。

  • valueSource - 值源,可以用来创建组件。

  • options - 选项对象,用于展示选项。

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

  • targetClass - 创建的组件的目标类型。例如,FormTableDataGrid

有两种内置组件策略:

  • DefaultComponentGenerationStrategy - 根据给定的 ComponentGenerationContext 对象创建组件。顺序值为 JmixOrder.LOWEST_PLATFORM_PRECEDENCE(1000)。顺序值越大表示优先级越低,最小的顺序值具有最高的优先级,相同的顺序值会导致随机排序。

  • CustomDatatypesComponentGenerationStrategy - 在其他策略不能生成组件时,根据数据类型(datatype)生成默认组件。例如,当数据类型是自定义类型时,而 DefaultComponentGenerationStrategy 创建的组件都不能匹配该类型。此策略具有顺序值 Integer.MAX_VALUE(0x7fffffff)。

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

@org.springframework.stereotype.Component("sample_SalesComponentGenerationStrategy")
public class SalesComponentGenerationStrategy implements ComponentGenerationStrategy, Ordered {

    @Inject
    private UiComponents uiComponents;

    @Inject
    private Metadata metadata;

    @Nullable
    @Override
    public Component createComponent(ComponentGenerationContext context) {
        String property = context.getProperty();
        MetaClass orderMetaClass = metadata.getClass(Order.class);

        if (orderMetaClass.equals(context.getMetaClass())
                && "date".equals(property) (1)
                && context.getClass() != null
                && Form.class.isAssignableFrom(context.getClass())) { (2)
            DatePicker<Date> datePicker = uiComponents.create(DatePicker.TYPE_DATE); (3)

            ValueSource valueSource = context.getValueSource();
            if (valueSource != null) {
                datePicker.setValueSource(valueSource); (4)
            }

            return datePicker;
        }

        return null;
    }

    @Override
    public int getOrder() {
        return 50; (5)
    }
}
1 检查 Order 实体的特定字段。
2 检查此时是为 Form 创建组件。
3 创建特定的 DatePicker 组件。
4 将组件绑定至值源。
5 返回该策略的顺序值。

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

@Order(100)
@org.springframework.stereotype.Component("sample_ColorComponentGenerationStrategy")
public class ColorComponentGenerationStrategy implements ComponentGenerationStrategy {

    @Inject
    private UiComponents uiComponents;

    @Nullable
    @Override
    public Component createComponent(ComponentGenerationContext context) {
        String property = context.getProperty();
        MetaPropertyPath mpp = context.getMetaClass().getPropertyPath(property);

        if (mpp != null) {
            Range mppRange = mpp.getRange();
            if (mppRange.isDatatype()
                    && (Datatype) mppRange.asDatatype() instanceof ColorDatatype) {
                ColorPicker colorPicker = uiComponents.create(ColorPicker.class);
                colorPicker.setDefaultCaptionEnabled(true);

                ValueSource valueSource = context.getValueSource();
                if (valueSource != null) {
                    colorPicker.setValueSource(valueSource);
                }
                return colorPicker;
            }
        }
        return null;
    }

}