3

我需要验证几个 Wicket 类型的输入字段TextField<BigDecimal>(即百分比总和为 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 保存在 Page 上的集合中,但是这种方法失败了,因为不仅首先创建了 Page,而且调用populateItem()了封闭的方法,因此将重复的字段添加到了集合中。ListView(我想不出一个简单的方法来保持它没有重复。)

使用 ListView 的事实似乎也使从validate()方法中的表单对象中查找字段变得有些复杂。我想我需要获取 ListViewform.get("shares")并遍历其子项?

访问中继器所包含的任意数量的字段的“正确方法”是ListView什么?

4

3 回答 3

5

另一种方法是子类化TextField,然后使用 aVisitor来挑选子类的所有后代组件。

通过这种方式,您可以避免未经检查的强制转换,并且您不必依赖 id,这不是一种非常可靠的方法。

编辑:在实践中,它看起来像这样:

子类:

private static class ShareField extends TextField<BigDecimal> {
   // ...
}

从表单中查找所有 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;
}
于 2012-05-30T20:51:02.380 回答
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-> TextField<BigDecimal>) 会产生“未经检查的强制转换”警告。

如果您可以清理此解决方案,或知道更好的方法,请随时发表评论或发布其他答案

于 2012-05-30T15:40:50.693 回答
2

据我所知,您没有在列表视图上设置重用项目属性;来自java文档:

如果窗口根本没有改变或者它被滚动(与分页相比),则重新渲染列表视图更有效。但是,如果您修改 listView 模型对象,则必须手动调用 listView.removeAll() 以重建 ListItems。如果您将 ListView 嵌套在 Form 中,请始终将此属性设置为 true,否则验证将无法正常工作。

但是,您也可以使用Visitor遍历列表视图的子项。Wicket 始终跟踪您添加的视图组件。

于 2012-05-30T16:59:41.337 回答