我需要验证类型为TextField<BigDecimal>
的几个Wicket输入字段的某些内容(即百分比之和为100)。有一到多个这样的输入字段;事情是,我事先并不知道有多少。
(简化示例)
private class PercentageValidator extends AbstractFormValidator {
@Override
public FormComponent<?>[] getDependentFormComponents() {
// ...
}
@Override
public void validate(Form<?> form) {
List<TextField<BigDecimal>> fields = // TODO
// the actual validation where the value of every field is needed
}
}
ListView的Java代码:
ListView<?> listView = new ListView<PropertyShare>("shares", shares) {
@Override
protected void populateItem(ListItem<PropertyShare> item) {
// ...
item.add(new TextField<BigDecimal>("share", ... model ...));
}
};
HTML:
<tr wicket:id="shares">
<td> ... </td>
<td>
<input wicket:id="share" type="text" size="4"> %
</td>
</tr>
我尝试将每个TextField保留在页面上的集合中,但这种方法失败,因为封闭populateItem()
的{{1}}方法不仅被调用,而且首先创建了Page,因此复制字段得到添加到集合中。 (我无法找到一种简单的方法来保持它没有重复。)
使用ListView这一事实似乎也有点使ListView
方法中的表单对象中的字段变得复杂。我想我需要使用validate()
获取ListView并遍历其子项?
访问form.get("shares")
等转发器所包含的任意数量字段的“正确方法”是什么?
答案 0 :(得分:5)
另一种方法是子类TextField
,然后使用Visitor
来挑选子类的所有后代组件。
通过这种方式,您可以避免未经检查的转换,并且您不必依赖于ID,这不是一种非常强大的方法。
修改:在实践中,它看起来像这样:
子类:
private static class ShareField extends TextField<BigDecimal> {
// ...
}
Helper方法,从表单中找到所有ShareField:
private List<ShareField> findShareFields(Form form) {
final List<ShareField> fields = Lists.newArrayList();
form.visitChildren(ShareField.class, new IVisitor<ShareField>() {
@Override
public Object component(ShareField component) {
fields.add(component);
return CONTINUE_TRAVERSAL;
}
});
return fields;
}
答案 1 :(得分:2)
是的,在写这个问题时,我突然意识到,简单地循环遍历form.get("shares")
的孩子并获得id为“share”的字段可能会有效。
@SuppressWarnings("unchecked")
private List<TextField<BigDecimal>> findFields(Form form) {
List<TextField<BigDecimal>> fields = Lists.newArrayList();
MarkupContainer container = (MarkupContainer) form.get("shares");
for (Iterator<? extends Component> it = container.iterator(); it.hasNext();) {
MarkupContainer c = (MarkupContainer) it.next();
fields.add((TextField<BigDecimal>) c.get("share"));
}
return fields;
}
但是,上述方法中有三个有点丑陋的演员表,其中一个(Component
- &gt; TextField<BigDecimal>
)会产生“未经检查的演员”警告。
如果您可以清理此解决方案,或了解更好的方法,随时发表评论或发布其他答案!
答案 2 :(得分:2)
到目前为止,我看到你没有在列表视图中设置reuse items属性;来自java doc:
如果真正重新渲染列表视图,如果窗口根本没有更改或者滚动(与分页相比),则效率更高。但是,如果修改listView模型对象,则必须手动调用listView.removeAll()才能重建ListItems。如果在表单中嵌套ListView,则ALLWAYS将此属性设置为true,否则验证将无法正常工作。
但是,您也可以使用Visitor迭代列表视图的子项。 Wicket始终跟踪您添加视图的组件。