在我当前的项目中,我希望能够在搜索引用对象时创建新对象。这发生在应用程序的几个地方。
例如,我们假设我们有一个城市实体和一个国家实体。 City实体具有对Country实体的强制引用。
在我的用例中,我想创建一个新城市。当我这样做时,我将不得不为新城市分配一个国家。当我点击查找图标时,我会看到所有现有国家/地区的选择对话框。但如果我没有我想要的国家,我必须中止操作,返回国家名单并创建我想分配给我的新城市的新名单。
我可以想象,从框架中可以提出很多要求。但我只是给出了一个镜头,也许还给出了一个新的功能想法,这将是很好的。
答案 0 :(得分:3)
自定义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操作。您可以为整个应用程序或每个参考视图全局执行:
'lovAction'
中声明名为frontend.groovy
的操作,即:action('lovAction', parent: 'lovActionBase', class:'test.LovActionWithCreate',
custom: [createAction_ref:'theCreateAction']
)
referencePropertyView
(在form
或table
中)及其'lovAction'属性来完成,例如: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;
}
}
如果您查看上面的代码,我们的新操作会处理以下事项:
第1点和第2点由getComponentToEdit
方法处理,第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;
}
}
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中查询引用属性时设置一些限制(静态或动态)。例如,让我们考虑以下用例:
Contract
和Tariff
,它们通过1-N关系链接在一起,即Contract
与1 Tariff
相关联。Contract
和Tariff
都有country
属性,Tariff
可以分配给Contract
当且仅当他们属于同一个国家/地区时Tarrif
具有status
属性,只有在Contract
为status
的情况下才能在ACTIVE
中使用。您可以通过以下方式在引用属性上设置初始化映射,在LOV中简单地强制执行这些规则:
Entity('Contract', ...) {
...
reference 'tariff', ref: 'Tariff',
initializationMapping: [
'country': 'country',
'status': 'ACTIVE'
]
...
}
考虑到这一点,这种行为可能会很好地找到框架,所以请随时在Jspresso GitHub中打开增强请求。