可插拔组件工厂
可插拔组件工厂机制扩展了标准组件的创建过程,支持在 Form、Table 和 DataGrid 中创建不同的编辑组件。也就是说,应用程序组件或你的应用程序项目本身可以提供自定义策略,以创建非标准的组件或支持自定义数据类型。
该机制的入口点是 UiComponentsGenerator.generate(ComponentGenerationContext)
方法。首先,尝试找到 ComponentGenerationStrategy(组件生成策略)
的实现;如果找到至少一种策略,然后会根据 org.springframework.core.Ordered
接口定义的顺序遍历这些策略;最后,返回创建的第一个非 null
组件。
ComponentGenerationStrategy
的实现用于创建 UI 组件。一个项目可以包含任意个这种策略。
创建组件时,ComponentGenerationContext
类存储可以使用的信息:
-
metaClass
- 实体类,指定为该实体创建组件。 -
property
- 实体属性,指定为该属性创建组件。 -
valueSource
- 值源,可以用来创建组件。 -
options
- 选项对象,用于展示选项。 -
xmlDescriptor
- 在组件以声明的方式在 XML 描述中定义时,包含附加信息的 XML 描述。 -
targetClass
- 创建的组件的目标类型。例如,Form
、Table
、DataGrid
。
有两种内置组件策略:
-
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;
}
}