我有一个用于编辑db实体的组件。它在onSuccess()上有@CommitAfter。当它在单独的页面上时,它工作正常。我点击更新按钮,它会保存数据并重定向到查看页面。
现在我想在列表页面上重复使用它。通过单击项目,它应该出现。在编辑并单击组件上的更新按钮后,它应该将项目保存到数据库并隐藏自己。
为了实现这个目的,我修改了组件,以便为其表单设置区域ID。将组件放在列表页面的区域内,为每个项目添加了带有事件onSelectItem的链接,它为组件设置区域ID并返回区域的主体。
它确实显示了组件,我可以编辑字段并点击更新按钮。它更新了项目,但将整个页面重定向到了查看页面。我试图在onSuccess()中返回null - 但在这种情况下它没有将数据保存到db并且区域也没有刷新。我还尝试使用@InjectPage从组件调用页面类并返回page.zone.getBody() - 这会重新加载区域,但仍然不保存数据,尽管所有方法都通过了w / o异常。在组件内调用特定于页面的代码也太糟糕了。我的其他自定义ajax调用使用@CommitAfter在方法中将数据保存到db。
所以我的问题是在Tapestry中这样做的正确方法是什么?
ContactsList.tml
<html t:type="layout" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd" xmlns:p="tapestry:parameter">
<t:form>
... list of contacts linked to onSelectContact()
</t:form>
<t:zone id="editContact" t:id="editContactZone">
<t:if test="selectedContact">
<t:contactform t:id="contactForm" />
</t:if>
</t:zone>
</html>
ListPage.java
public class ContactsList{
@InjectComponent
private Zone editContactZone;
@InjectComponent("contactForm")
private ContactForm contactForm;
@Property
private Contact selectedContact;
public Object onSelectContact(@RequestParameter(value = "id", allowBlank = false) Integer id) {
selectedContact = getContactById(id);
if (selectedContact != null) {
contactForm.setContact(selectedContact);
contactForm.setFormZone(editContactZone.getClientId());
}
return editContactZone.getBody();
}
}
ContactForm.tml
<div xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" xmlns:p="tapestry:parameter">
<t:form t:id="editContactForm" zone="prop:zone">
.... contact fields
</t:form>
</div>
ContactForm.java
public class ContactForm{
@InjectComponent("editContactForm")
private Form editContactForm;
@Property
private String zone;
@InjectPage
private ContactList listPage;
@InjectPage
private ViewContact viewContact;
@Property
protected Contact contact;
public void setContact(Contact contact) {
this.contact = contact;
}
public void setFormZone(String zone){
this.zone = zone;
}
@CommitAfter
public Object onSuccess() {
parseContact();
storeContact(); // calls DAO.store(contact)
return zone == null ? viewContact : listPage.onSelectContact(0); //don't like this in component code but at least it returns zone's body
}
}
答案 0 :(得分:1)
您可以将Block组件参数传递给包含要在@OnSuccess之后呈现的标记的ContactForm。
或许更好的关注点分离是触发ContactForm中的一个事件,它会冒泡到页面?例如:
ContactForm.java
@Inject ComponentResources resources;
@CommitAfter
public void onSuccess() {
storeContact();
resources.triggerEvent("contactSaved", new Object[] { contact }, null);
}
ContactsList.java
@Inject AjaxResponseRenderer ajaxRenderer;
@Inject Zone someZone;
@Property Contact contact;
public void onContactSaved(Contact contact) {
this.contact = contact;
ajaxRenderer.addRender(someZone);
}
另外,你为什么要使用@RequestParameter?为什么不使用事件上下文?
ContactsList.tml
<t:loop source="contacts" item="contact">
<t:eventlink event="selectContact" context="contact">Edit ${contact.name}</t:eventlink>
</t:loop>
ContactList.java
Block onSelectContact(Contact contact) {
// doStuff
}