LOV 对话框的自定义:
您可以通过创建您自己的安装在参考字段旁边的 LOV 操作类轻松自定义 LOV 对话框。
public class LovActionWithCreate<E, F, G> extends LovAction<E, F, G> {
private IDisplayableAction createAction;
@Override
protected void feedContextWithDialog(IReferencePropertyDescriptor<IComponent> erqDescriptor,
IQueryComponent queryComponent, IView<E> lovView, IActionHandler actionHandler,
Map<String, Object> context) {
super.feedContextWithDialog(erqDescriptor, queryComponent, lovView, actionHandler, context);
List<IDisplayableAction> defaultLovDialogActions = (List<IDisplayableAction>) context.get(
ModalDialogAction.DIALOG_ACTIONS);
defaultLovDialogActions.add(1, getCreateAction());
}
/**
* Gets create action.
*
* @return the create action
*/
protected IDisplayableAction getCreateAction() {
return createAction;
}
/**
* Sets create action.
*
* @param createAction
* the create action
*/
public void setCreateAction(IDisplayableAction createAction) {
this.createAction = createAction;
}
}
关键是要覆盖该feedContextWithDialog
方法,以便将新操作安装到对话框中。
下一步是安装新的 LOV 操作。您可以为整个应用程序或每个参考视图全局执行此操作:
- 全局替换 LOV 操作只是在
'lovAction'
您的应用程序中声明一个名为的操作frontend.groovy
,即:
action('lovAction', parent: 'lovActionBase', class:'test.LovActionWithCreate',
custom: [createAction_ref:'theCreateAction']
)
referencePropertyView
可以通过使用(in aform
或 in a table
) 及其 'lovAction' 属性来替换表单中某个参考字段上的 LOV 操作,例如:
action('lovActionWithCreate', parent: 'lovActionBase', class:'test.LovActionWithCreate',
custom: [createAction_ref:'theCreateAction']
)
form('ACertainForm'){
fields {
...
referencePropertyView name:'country', lovAction:'lovActionWithCreate'
...
}
}
在 LOV 对话框中创建实体:
在下一步中,我们将创建将负责打开额外对话框的操作,以创建新实体并将其持久化,如果成功,则将其添加到 LOV 结果视图。这有点复杂,但不是那么多。
为此,我们将继承内置的EditComponentAction
. 此操作的目标是在模态对话框中编辑模型。这里唯一的困难是我们的模型只在运行时才知道。没问题,因为我们将使用 Jspresso 的动态特性。
public class CreateEntityFromLOVAction<E, F, G> extends EditComponentAction<E,F,G> {
@Override
protected Object getComponentToEdit(Map<String, Object> context) {
IEntityFactory entityFactory = getBackendController(context).getEntityFactory();
IQueryComponent lovQueryComponent = (IQueryComponent) context.get(IQueryComponent.QUERY_COMPONENT);
Class<IEntity> entityToCreateContract = lovQueryComponent.getQueryContract();
IEntity entityInstance = entityFactory.createEntityInstance(entityToCreateContract);
setActionParameter(Arrays.asList(entityInstance), context);
return entityInstance;
}
@Override
protected IViewDescriptor getViewDescriptor(Map<String, Object> context) {
IEntityFactory entityFactory = getBackendController(context).getEntityFactory();
IQueryComponent lovQueryComponent = (IQueryComponent) context.get(IQueryComponent.QUERY_COMPONENT);
Class<IEntity> entityToCreateContract = lovQueryComponent.getQueryContract();
IComponentDescriptor<?> entityToCreateDescriptor = entityFactory.getComponentDescriptor(entityToCreateContract);
BasicComponentViewDescriptor formViewDescriptor = new BasicComponentViewDescriptor();
formViewDescriptor.setModelDescriptor(entityToCreateDescriptor);
return formViewDescriptor;
}
}
如果您查看上面的代码,我们的新操作会处理以下内容:
- 从上下文中获取要创建的实体类型。为此,我们只是探索作为 LOV 对话模型的查询组件。
- 创建实体实例并将其设置为上下文中的操作参数,以便链继续对其进行处理(保存、关闭对话框)。
- 创建要在创建对话框中显示的表单。
第 1 点和第 2getComponentToEdit
点由方法处理,第 3 点由getViewDescriptor
方法处理。
- 接下来,当用户单击 时
Ok
,我们必须保存实体,将其添加到 LOV 结果列表并关闭创建对话框。
为此,我们将创建一个新动作并将其链接到saveAction
内置closeDialogAction
动作。
public class CreateEntityFromLOVPersistAction<E, F, G> extends FrontendAction<E,F,G> {
@Override
public boolean execute(IActionHandler actionHandler, Map<String, Object> context) {
if (super.execute(actionHandler, context)) {
IQueryComponent lovQueryComponent = (IQueryComponent) context.get(IQueryComponent.QUERY_COMPONENT);
List<IEntity> createdEntityInstance = getActionParameter(context);
lovQueryComponent.setQueriedComponents(createdEntityInstance);
return true;
}
return false;
}
}
- SJS 中的最终布线
frontend.groovy
:
action('createEntityFromLovOkAction', parent: 'okDialogFrontAction',
class:'test.CreateEntityFromLOVPersistAction',
wrapped: 'saveBackAction', next: 'closeDialogAction')
action('createEntityFromLovAction', parent: 'editComponentAction',
class: 'test.CreateEntityFromLOVAction',
name:'add.name', custom: [
okAction_ref: 'createEntityFromLovOkAction'
]
)
action('lovAction', parent: 'lovActionBase',
class:'test.LovActionWithCreate',
custom: [createAction_ref:'createEntityFromLovAction']
)
不到 100 行代码的长答案,但现在您拥有一个完全通用的 LOV 操作,用户可以在其中创建任何缺失的主数据,而无需离开当前屏幕。
根据用户上下文在 LOV 过滤器中预设一些数据:
为此,我们通常使用允许在 LOV 中查询引用属性时设置一些限制(静态或动态)的初始化映射。例如,让我们考虑以下用例:
- 您有 2 个实体
Contract
和Tariff
,它们通过 1-N 关系链接在一起,即 aContract
链接到 1 Tariff
。
Contract
并且Tariff
两者都有一个country
属性,并且当且仅当它们属于同一个国家时,Tariff
才能将 a 分配给 a 。Contract
Tarrif
有一个status
属性,并且只能在 a 中使用,Contract
如果它status
是ACTIVE
。
您可以通过以下方式在引用属性上设置初始化映射来简单地在 LOV 中强制执行这些规则:
Entity('Contract', ...) {
...
reference 'tariff', ref: 'Tariff',
initializationMapping: [
'country': 'country',
'status': 'ACTIVE'
]
...
}
想一想,这种行为很可能会在框架中找到,所以请随时在Jspresso GitHub中打开增强请求。