Wicket:隐藏组件而不必添加所有子组件

时间:2016-12-16 13:20:46

标签: java wicket wicket-6

我一直在Wicket做一个项目,我经常发现自己陷入了困境。让我们说我有一个标记,我只在某些条件适用时显示,如下例所示:

<div wicket:id="myContainer">
    <div wicket:id="label1"></div>
    <div wicket:id="label2"></div>
    <div wicket:id="label3"></div>
    <div wicket:id="label4"></div>
</div>

并在我的Java代码中:

WebMarkupContainer myContainer = new WebMarkupContainer("myContainer");
add(myContainer);

if(myDataObject != null){
    myContainer.add(new Label("label1", myDataObject.getData1());
    myContainer.add(new Label("label2", myDataObject.getData2());
    myContainer.add(new Label("label3", myDataObject.getData3());
    myContainer.add(new Label("label4", myDataObject.getData4());
} else{
    //HAVING TO DO THIS IS ABSURD!
   myContainer.add(new Label("label1", "");
   myContainer.add(new Label("label2", "");
   myContainer.add(new Label("label3", "");
   myContainer.add(new Label("label4", "");
   myContainer.setVisible(false);
}

正如你所看到的,即使在我不打算显示它的情况下,我也不得不在容器中添加虚拟组件,否则Wicket会抛出异常,说我在标记中有组件我没有在代码中添加。

对我而言,这是荒谬的,必须实例化我将不会显示的额外组件是浪费,耗时并且使代码不必要地可读。

我希望这只是我对Wicket的无知,并且有人可以告诉我一种允许我放弃一个组件和所有孩子的方法。

3 个答案:

答案 0 :(得分:5)

你可以改进你的代码很多,所以它变得不那么痛苦了:)

这是使用CompoundPropertyModel的好地方。

此外,只需控制容器的onConfigure()中的可见性。

WebMarkupContainer myContainer = new WebMarkupContainer("myContainer", new CompoundPropertyModel(myDataObject))
{
    public void onConfigure()
    {
        setVisible( this.getModelObject() != null);
    }
}

add(myContainer);

myContainer.add(new Label("data1"));
myContainer.add(new Label("data2"));
myContainer.add(new Label("data3"));
myContainer.add(new Label("data4"));

替代

您使用WebMarkupContainer的方式建议您也可以使用Panel为此“myDataObject”构建一个漂亮的显示组件

<强>爪哇

public class MyDataObjectPanel extends Panel
{
    public MyDataObjectPanel(String id, IModel<MyDataObject> myDataObjectModel)
    {
        super(id,  new CompoundPropertyModel(myDataObjectModel);
        this.add(new Label("data1"));
        this.add(new Label("data2"));
        this.add(new Label("data3"));
        this.add(new Label("data4"));
    }

    public void onConfigure()
    {
        setVisible( this.getModelObject() != null);
    }

}

<强> HTML

<wicket:panel>
    <div wicket:id="data1"></div>
    <div wicket:id="data2"></div>
    <div wicket:id="data3"></div>
    <div wicket:id="data4"></div>
</wicket:panel>

然后,您想要显示它的所有地方,只需使用此面板。

<小时/> 我会建议反对这个(因为它会让你的代码变得更复杂,我认为你不会赢得很多性能),但如果你真的不关心不向wicket组件添加元素-tree,你可以下一个代码。它决定是否显示专用组件,替换实际组件:

public class MainComponent {

    @Override
    protected void onConfigure()
    {
        MyDataObject obj = getDataObjectFromSomeModel();
        if (obj == null) {
            this.addOrReplace( new EmptyPanel("dataPanelId").setVisible(false));
        }
        else {
            this.addOrReplace( new MyDataObjectPanel("dataPanelId"));   
        }
    }
}

答案 1 :(得分:3)

我现在没有时间尝试,但我很确定

} else{
  myContainer.setVisible(false);
}

应该有效。 如果父组件根本没有渲染,Wicket不会抱怨孩子丢失了。

答案 2 :(得分:2)

不要认为成本很高。

不可见组件不执行许多方法,最重要的方法是onRender()和onComponentTag()。模型不执行getObject()。 从html生成的角度看,可见成本为零。 附加信息: https://ci.apache.org/projects/wicket/guide/7.x/guide/componentLifecycle.html

根据当前版本7.5.0检查我的知识

我认为组件(隐形)必须存在,这是正常的Wicket哲学。隐形组件很轻巧。

BTW我不确定你的myDataObject是wicket模型。 我同意doc中的建议:使用模型

代码将更清晰,没有这样的'if' - 我更喜欢不使用分支实例化 - 但是使用正确的模型。

在构造函数中避免使用太多“活动”代码,例如,不要获取值,让我们通过Model获取有条件(延迟)。 捕获Wicket构造函数中抛出的异常是很难看的。但是应用程序可以很好地捕获渲染阶段的异常。

最后,请记住,这些是隐藏组件的两个策略,一个是静态的,另一个是动态的: https://ci.apache.org/projects/wicket/guide/7.x/guide/keepControl.html#keepControl_1