EntityPicker 实体选择器
基本用法
满足下列情况可以使用 EntityPicker:
-
字段值是实体实例。
-
用户需要通过查找界面或通过输入特定值选择或创建实体。
-
用户需要为关联实体打开编辑界面。
Jmix Studio 创建实体编辑器时,会默认为实体引用属性生成 EntityPicker。
在下面的例子中,界面为具有 customer 属性的 Order 实体定义了 id 为 orderDc 的数据容器。在 entityPicker 元素中,通过 dataContainer 属性连接到 orderDc 数据容器,并给 property 属性设置了 customer 实体属性。实体属性是另一实体的引用,在上面的示例中就是 Customer 实体。
<data>
<instance id="orderDc"
class="ui.ex1.entity.Order">
<fetchPlan extends="_base">
<property name="customer" fetchPlan="_instance_name"/>
</fetchPlan>
<loader/>
</instance>
</data>
<layout spacing="true">
<vbox spacing="true" id="vbox">
<entityPicker id="customerField"
dataContainer="orderDc"
property="customer"
caption="msg://ui.ex1.entity/Order.customer">
<actions>
<action id="lookup" type="entity_lookup"/>
<action id="clear" type="entity_clear"/>
</actions>
</entityPicker>
</vbox>
</layout>
|
为了让 |
操作
可以给 EntityPicker 设置自定义或预定义的操作,操作作为按钮显示在右侧。
定义操作可以在 XML 中用 actions 元素或者在控制器中用 addAction() 方法编程式添加。
|
如需在 Jmix Studio 中添加 |
预定义操作
当 Studio 在编辑界面生成 EntityPicker 时,还会同时生成两个预定义的操作:entity_lookup 和 entity_clear。此外,还支持 entity_open 和 entity_openComposition 操作。
用 type 和 id 属性在 XML 中配置预定义操作。
如果创建无操作的 EntityPicker,XML 加载器仅定义 entity_lookup 和 entity_clear 操作。如需添加其他预定义操作,例如,entity_open,可以按照下面这样指定 actions 元素:
<entityPicker dataContainer="orderDc"
property="customer"
caption="msg://ui.ex1.entity/Order.customer">
<actions>
<action id="lookup" type="entity_lookup"/>
<action id="open" type="entity_open"/>
<action id="clear" type="entity_clear"/>
</actions>
</entityPicker>
actions 元素不是对标准操作进行扩展,而是进行覆盖。因此,需要明确定义所有必需操作的标识符。
自定义操作
如需在 XML 中定义自定义操作,可以使用内部的 actions 元素。为 action 指定 id 和 icon 属性:
<entityPicker id="customerEntityPicker"
property="customer"
dataContainer="orderDc">
<actions>
<action id="lookup" type="entity_lookup"/>
<action id="points"
icon="QUESTION"
description="msg://knowPoints"/>
</actions>
</entityPicker>
然后在界面控制器订阅 Action.ActionPerformedEvent 实现自定义逻辑:
@Autowired
private EntityPicker<Customer> customerEntityPicker;
@Autowired
private Notifications notifications;
@Subscribe("customerEntityPicker.points") (1)
public void onCustomerEntityPickerPoints(Action.ActionPerformedEvent event) {
Customer customer = customerEntityPicker.getValue();
if (customer != null) {
notifications.create()
.withCaption(customer.getFirstName() +
" has " + customer.getRewardPoints() +
" reward points")
.show();
} else {
notifications.create()
.withCaption("Choose a customer")
.show();
}
}
| 1 | @Subscribe 注解包含 EntityPicker 的 id 以及操作的 id,以“.”分隔。 |
|
可以用 Studio 生成处理 |
编程式添加操作
使用 addAction() 以编程方式添加操作。
-
添加标准操作
例如,如果在组件的 XML 描述中没有内部的
actions元素,就可以使用这个方法添加缺少的标准操作:@Autowired private Actions actions; @Autowired private EntityPicker<Customer> entityPicker; @Subscribe public void onInit(InitEvent event) { entityPicker.addAction(actions.create(EntityOpenAction.class)); } -
添加自定义操作
创建自定义操作的示例:
@Autowired private EntityPicker<Customer> customerEp; @Subscribe public void onInit(InitEvent event) { customerEp.addAction(new BaseAction("showLevel") .withCaption(null) .withDescription(null) .withIcon(JmixIcon.VIEW_ACTION.source()) .withHandler(e -> { Customer customer = customerEp.getValue(); if (customer != null) { notifications.create() .withCaption(customer.getFirstName() + " " + customer.getLastName() + "'s level is " + customer.getLevel()) .show(); } else { notifications.create() .withCaption("Choose a customer") .show(); } })); }
MetaClass
可以在不绑定数据容器的情况下使用 EntityPicker,即不设置 dataContainer 和 property 属性。在这种情况下,需要使用 metaClass 属性指定 EntityPicker 的实体类型。示例:
<entityPicker id="custPicker" metaClass="uiex1_Customer">
<actions>
<action id="lookup" type="entity_lookup"/>
<action id="open" type="entity_open"/>
</actions>
</entityPicker>
可以通过将组件注入控制器并调用其 getValue() 方法来获取所选实体的实例。
设置图标
EntityPicker 左侧可以有图标。只需要在界面控制器注册 fieldIconProvider 并实现自定义逻辑:
@Install(to = "customerField", subject = "fieldIconProvider")
private String customerFieldFieldIconProvider(Customer customer) { (1)
return (customer != null) ? "font-icon:CHECK" : "font-icon:BAN";
}
| 1 | fieldIconProvider 代理方法实现。 |
参阅 图标 了解更多关于使用图标的内容。
如需编程式注册字段的图标 provider,使用组件的 setFieldIconProvider() 方法。
输入文本值
默认情况下,用户不能手动输入值。如果设置 fieldEditable 属性为 true,则启用手动输入功能。这个功能可以用来根据用户输入的值创建实体实例。
需要注意,输入的值不会设置给数据模型。用 FieldValueChangeEvent 处理用户输入。
下面的例子中,我们有 Address 实体,此实体的 country 属性关联至 Country 实体。Country 实体只有一个 name 属性。我们在 XML 中定义 countryField 的属性 fieldEditable="true":
<entityPicker id="countryField" property="country" fieldEditable="true">
<actions>
<action id="lookup" type="entity_lookup"/>
<action id="clear" type="entity_clear"/>
</actions>
</entityPicker>
现在用户可以手动输入值了。如需处理该值(字符串格式),在控制器中订阅 FieldValueChangeEvent 事件:
@Autowired
private DataContext dataContext;
private Country country;
@Autowired
private TextField<String> addressField;
@Autowired
private EntityPicker<Country> countryField;
@Autowired
private Dialogs dialogs;
@Subscribe("countryField") (1)
public void onCountryFieldFieldValueChange(ValuePicker.FieldValueChangeEvent<Country>
event) {
String value = event.getText(); (2)
if (!Strings.isNullOrEmpty(value)) {
country = dataContext.create(Country.class); (3)
country.setName(value);
countryField.setValue(country); (4)
}
}
| 1 | @Subscribe 注解包含 EntityPicker id。 |
| 2 | 从事件对象中获取输入的值。 |
| 3 | 创建一个 Country 实体实例。 |
| 4 | 将创建的实例设置给该字控件。 |
如需以编程的方式注册事件处理器,使用组件的 addFieldValueChangeListener() 方法。
编程式创建 EntityPicker
如需在控制器中创建 EntityPicker,可以使用 UiComponents 工厂。需要注意的是,以编程方式创建的 EntityPicker 无默认操作,需要手动添加必须的操作:
@Autowired
private Metadata metadata;
@Autowired
private UiComponents uiComponents;
@Autowired
private Actions actions;
@Subscribe
public void onInit(InitEvent event) {
EntityPicker<User> userPicker = uiComponents.create(EntityPicker.of(User.class));
userPicker.setMetaClass(metadata.getClass(User.class));
userPicker.addAction(actions.create(EntityLookupAction.class));
userPicker.addAction(actions.create(EntityOpenAction.class));
userPicker.addAction(actions.create(EntityClearAction.class));
vbox.add(userPicker);
}
事件和处理器
|
如需使用 Jmix Studio 生成处理器的桩代码,需要在界面 XML 描述或者 Jmix UI 层级结构面板选中该组件,然后用 Jmix UI 组件面板的 Handlers 标签页生成。 或者可以使用界面控制器顶部面板的 Generate Handler 按钮。 |
FieldIconProvider
参阅 Setting Icons。
Formatter
为组件添加一个 formatter。
下面的例子中,我们展示 customerFormat 实体选择控件 formatter 的用法:
@Install(to = "customerFormat", subject = "formatter")
protected String customerFormatFormatter(Customer value) {
return value != null ? value.getFirstName() + " " + value.getLastName() : null;
}
如需以编程的方式添加 formatter,使用组件的 addFormatter() 方法。
Validator
参阅 Validator。
ValueChangeEvent
参阅 ValueChangeEvent。
EntityPicker XML 属性
|
可以使用 Studio 界面设计器的 Jmix UI 组件面板查看和编辑组件的属性。 |
align - buffered - caption - captionAsHtml - colspan - contextHelpText - contextHelpTextHtmlEnabled - css - dataContainer - description - descriptionAsHtml - editable - enable - box.expandRatio - fieldEditable - height - htmlSanitizerEnabled - icon - id - inputPrompt - metaClass - property - required - requiredMessage - stylename - tabIndex - visible - width