we are encountering an issue with Tapestry (version 5.7.2) and zone refreshing from components.
We have a page that contains a loop of (zoned) components, where each component has a async event (see code).
What we want to achieve, is that via the XHR refresh, we refresh both the component zone and another zone that is contained by the page, which we get via an interface.
In this code example, when we click on the first component, it refreshes the zone but 'forgets' the @Persist annotated field, which takes the value of the second component.
If we click on the second component instead, it refreshes the first one too.
What are we doing wrong? seems trivial zone refreshing but we didn't get it, we tried different approaches but must fallback to handle this part in a less elegant way.
Page code:
@InjectComponent
private Zone listingZone;
@Persist
private String[] names;
@Property
private String lastRefreshZoneName;
@Property
private String _name;
Object onActivate() throws Exception {
names = new String[]{"first","second"}; //eg. loaded from DB
return null;
}
public LocalDateTime getTime() {
return LocalDateTime.now();
}
public String[] getNames() {
return names;
}
@Override
public Zone getOuterZone() {
return listingZone;
}
@Override
public void onTriggerOn(String name) {
lastRefreshZoneName = name;
}
with a simple TML as such:
<t:zone t:id="pageZone">
Page zone: ${time}<br/>
<hr/>
<t:loop source="names" value="name">
<t:attribute.zonedcomponent t:parameter="${name}"/>
</t:loop>
<hr/>
<t:zone t:id="listingZone">
Listing zone, last refresh: ${time}<br/>
Last refresh zone name: ${lastRefreshZoneName}
</t:zone>
</t:zone>
for this example, ZonedComponent is a component with a zone and a event link as such:
@Inject
private Request request;
@Inject
private AjaxResponseRenderer ajaxResponseRenderer;
@Inject
private ComponentResources resources;
@InjectComponent
private Zone componentZone;
@Parameter(defaultPrefix = BindingConstants.LITERAL)
private String parameter;
@Persist
@Property
private String name;
void setupRender() {
this.name = parameter;
}
public LocalDateTime getTime() {
return LocalDateTime.now();
}
void onTrigger(String name) {
if (request.isXHR()) {
// this.name = name; // if we don't uncomment this, then it doesnt even propagate the 'name' correctly
SomeInterface page = (SomeInterface)resources.getPage();
page.onTriggerOn(this.name);
ajaxResponseRenderer.addRender(componentZone)
.addRender(page.getOuterZone());
}
}
public static interface SomeInterface {
ClientBodyElement getOuterZone();
void onTriggerOn(String name);
}
with the tml zone as such:
<t:zone t:id="componentZone" style="border:1px solid black">
Component name: ${name}<br/>
Component zone: ${time}<br/>
<t:eventlink t:event="trigger" t:context="${name}" async="true">
async event from ${name}
</t:eventlink>
</t:zone>