我经常使用自定义Wicket组件来呈现模型对象。当对象为空时,会显示特定的div。因此,在组件HTML渲染代码中,我有两个div,一个用于“null”情况,另一个用于“非null”情况,并带有一些其他内部标记。其中一个被显示,而另一个则被遮盖。
<div wicket:id="toDisplayWhenObjectIsNull">
...
</div>
<div wicket:id="toDisplayWhenObjectIsNotNull">
<span wicket:id="label">...</span>
<table wicket:id="table">...</table>
...
</div>
我面临的问题是Wicket强制我完全构建这两个div,即使模型对象为null。在所有子组件构建(标签、表格等)的调用中,我必须检查是否为空,这很麻烦并容易出错:
X myX = getModel().getModelObject();
Label label = new Label("label",
myX == null ? null : formatY(myX.getY()));
第一种解决方法是将非空部分拆分为特定的wicket子组件,可以作为自己的类或主组件的内部类;并将该组件插入到“非空”div的位置。但这会使所需的文件数(资源、HTML和Java代码)翻倍。这不是理想的解决方案。
第二种通用解决方法是创建一个“装饰器”组件来封装任何其他组件,并检查其模型对象是否为空。如果组件为空,则显示标准div;否则,它将依赖于装饰的组件。我尝试使用边框或复合面板实现此目的,但无法使其正常工作。我想实现的效果类似于这样:
// Client code, Java
ViewXPanel xpanel = new ViewXPanel("xpanel", new Model<X>(x));
add(xpanel);
// HTML
<div wicket:id="xpanel"/>
或者,必要时使客户端负责展示组件的“可空性”,在客户端代码中使用类似以下代码:
// Client code, Java
ViewXPanel xpanel = new NullableDecorator(?, ViewXPanel(...));
add(xpanel);
Border
来解决?虽然这是一个常见的情况,但我从未需要过通用的解决方案。要么很容易只需创建两个div
元素,要么就更复杂一些,需要创建一个包装组件。无论如何,我敢打赌你可以创建一个ShowOneBorder(Component1, Component2, IModel<?>)
,它可以正确地添加它们并使用onConfigure()
修改其中一个以使其可见。 - jbrookover