我正在尝试基于TextField
(核心),DialogLink
(tapestry5-jquery)和Dialog
构建名为 CrudEntityField 的Tapestry组件( tapestry5-jquery)组件,以及用于AJAX更新的Zone
。
我的用例非常简单:
CrudEntityField将呈现为TextField。如果您知道实体ID, 你可以直接在那里输入。如果你不知道id,你可以 单击
DialogLink
按钮(SELECT),弹出一个Dialog 窗口。对话框以表格格式列出所有可用实体 让我们按一些标准过滤。一旦用户选择了实体,那么 文本字段会自动刷新相关的ID(例如“6”)。 此外,为了清楚起见,打印相关的名称/描述(例如, '[吉普斯格瓦]')。 快照:CrudEntityField,Pop-up Dialog
理想情况下,所有这些逻辑都可以封装在单个 Tapestry组件中。但问题出现了:
对话框(<div t:type="jquery/dialog" t:clientId="dialogIdXXX">
,见下文)包含一个搜索表单,它本身嵌入在另一个表单(CRUD表单)中。由于不允许使用嵌套表单,我可以尝试取消嵌套。但是,这种方法会失败,因为在我有机会移动它之前,我会在内部表单渲染时遇到运行时异常。
@AfterRender
public void afterRender(MarkupWriter writer) {
Element body = writer.getDocument().find("html/body");
writer.getDocument().getElementById("dialogIdXXX").moveToBottom(body);
}
我尝试了其他方法,例如@HeartbeatDeferred
,RenderCommand
等,但我发现无法将对话框从表单中删除。
组件模板:
<t:content>
<!-- A) Entity Field -->
<t:zone t:id="entityZone" id="zoneIdXXX">
<div class="inputElement">
<t:label for="textField"/>
<input t:id="textField"/>
[<t:body/>]
<t:jquery.dialoglink t:dialog="dialogIdXXX" class="dialogLink">SELECT</t:jquery.dialoglink>
</div>
</t:zone>
<!-- B) Entity Dialog -->
<div t:type="jquery/dialog" t:clientId="dialogIdXXX" params="params" >
<table t:id="xa2grid" t:entity="inherit:entity" t:add="actions">
<p:actionsCell>
<a t:type="EventLink" t:event="SELECT" t:zone="zoneIdXXX" t:context="entity.id" href="#">SELECT</a>
</p:actionsCell>
</table>
</div>
</t:content>
好的,所以我可以将组件拆分为两部分:EntityField
(表单输入字段)和EntityDialog
(放在表单中,在页面模板中)。然而,并不是优雅的,因为这种方法打破了抽象。
但这种做法也不会奏效。区域事件现在由EntityDialog
组件触发,必须由其自身或其中一个容器处理。但该区域在EntityField
中定义,现在是兄弟姐妹! (如果不清楚,我可以粘贴更多代码。)
答案 0 :(得分:0)
正如您所见,您无法在表单中呈现表单,因此您需要延迟对话框的呈现,直到表单呈现完毕为止。
因此,不要在组件中呈现对话框,而是使用环境bean。环境将存储页面上所有对话框的配置
http://tapestry.apache.org/environmental-services.html
在每个页面末尾添加一个块,从环境中查找配置并呈现所有对话框。希望您使用的是layout所以这将在一个地方。
例如: Layout.java
@Inject
Environment environment;
@Property
private DialogConfigs dialogConfigs;
@Property
private DialogConfig dialogConfig;
void beforeRender() {
dialogConfigs = new DialogConfigsImpl();
environment.push(DialogConfigs.class, dialogConfigs);
}
void afterRender() {
environment.pop(DialogConfigs.class);
}
Layout.tml
<html>
<body>
<t:body/>
<t:loop source="dialogConfigs.values" value="dialogConfig">
<div t:type="jquery/dialog" foo="dialogConfig.foo" bar="dialogConfig.bar">
</t:loop>
</body>
</html>
CrudEntityField.java
@Environmental
private DialogConfigs dialogConfigs;
@Parameter
private String foo;
@Parameter
private String bar;
void beforeRender() {
dialogConfigs.add(new DialogConfig(foo, bar));
}