【发布时间】:2013-12-17 14:58:28
【问题描述】:
我有一个可以在一个区域内使用的组件,它由一个选择更新。
这大概是我的组件的样子:
<div>
<input
t:type="textfield"
t:id="integerPart"
class="integerPart ${cssClass}"/>
</div>
这大概是区域的样子:
<t:zone t:id="myZone" id="myZone">
<t:mycomponent />
</t:zone>
When the select triggers the zone update the input is correctly updated with the given value.提交页面后,我对用户输入的值和数据库中的值进行了一些深入的计算。当触发错误时,我会在 ValidationTracker 中记录该错误,然后页面将被刷新,错误会显示在我页面上的全局标记中。
问题是当页面刷新并显示错误消息时,我的文本字段的值丢失了。原因是 Tapestry 重写了区域内的 id: http://tapestry.apache.org/ajax-components-faq.html
以及AbstractTextField中的这两个实现方法:
@BeginRender
void begin(MarkupWriter writer)
{
String value = tracker.getInput(this);
// lots of code
}
@Override
protected void processSubmission(String controlName)
{
String rawValue = request.getParameter(controlName);
tracker.recordInput(this, rawValue);
// lots of code
}
提交页面时调用processSubmission,并且我的文本字段中的当前值存储在由id标识的映射中:“integerPart_12a820cc40e”,而当重新加载页面以显示错误消息时再次打印组件在地图中查找键“integerPart”。这不会产生匹配,并且文本字段将呈现为空(即值丢失)。
我认为这是 Tapestry 中的一个已知问题,应该有一个快速简单的解决方案。我现在正在以一种“不那么快速和简单”的方式解决这个问题,感觉完全错误。
我扩展了 TextField,并使用 id 存储值:“integerPart”而不是“integerPart_12a820cc40e”。这是由这个类完成的:
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.Field;
import org.apache.tapestry5.ValidationTracker;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.corelib.components.TextField;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.Request;
public class ZoneFriendlyTextField extends TextField {
@Inject
private Request request;
@Environmental
private ValidationTracker tracker;
// copied from Abstract Field - to be able to use it here
@Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL)
private String localClientId;
@Override
protected void processSubmission(String controlName)
{
super.processSubmission(controlName);
String submittedValue = request.getParameter(controlName);
tracker.recordInput(new TextFieldInternalField(localClientId), submittedValue);
}
/**
* This class is only used since the controlName of DateFieldset in a zone returns with a random id and
* it is not possible to match against the right value when page-errors occur and we have to present
* the user with the user-entered values again.
* Should only be used for recording input in the tracker.
*/
private static class TextFieldInternalField implements Field {
String clientId;
private TextFieldInternalField(String clientId) {
this.clientId = clientId;
}
@Override
public String getClientId() {
return null;
}
@Override
public String getControlName() {
return clientId;
}
@Override
public String getLabel() {
return null;
}
@Override
public boolean isDisabled() {
return false;
}
@Override
public boolean isRequired() {
return false;
}
}
}
如果有人能提出更好的解决方案来解决这个问题,我将不胜感激! :-)
注意:在收到 Lance Java 的回复后,我对这个问题进行了一些改进。他对我最初的问题给出了很好的回答 - 但我认为这对我没有帮助,因为我的文本字段位于一个组件中,可以在一页中多次使用。
【问题讨论】:
标签: tapestry