6

我有一个块级元素,一个容器,当它的所有子 Wicket 元素(按钮)都被隐藏时,它应该被隐藏。换句话说,如果任何子按钮可见,则容器应该可见。

早些时候,如果有任何按钮,其中一个按钮总是可见的,因此我使用该按钮来控制 a 的可见性<wicket:enclosure>,纯粹在 HTML 端处理所有这些。

现在,规格已更改,因此按钮可以独立隐藏/可见,因此简单的外壳将不再起作用(我认为)。

我得到它的工作是这样的:

HTML:

<wicket:container wicket:id="downloadButtons">
     <wicket:message key="download.foo.bar"/>:
     <input type="button" wicket:id="excelDownloadButton" wicket:message="value:download.excel"/>
     <input type="button" wicket:id="textDownloadButton" wicket:message="value:download.text"/>
     <!-- etc ... -->
</wicket:container>

爪哇:

WebMarkupContainer container = new WebMarkupContainer("downloadButtons");

// ... add buttons to container ...

boolean showContainer = false;
Iterator<? extends Component> it = container.iterator();
while (it.hasNext()) {
    if (it.next().isVisible()) {
        showContainer = true;
        break;
    }
}
addOrReplace(container.setVisible(showContainer));

但是 Java 方面现在有点冗长和丑陋,我在想可能有一种更清洁的方法来做同样的事情。在那儿?当容器的所有子组件都不可见时,您能否以某种方式“自动”隐藏容器(及其所有附加标记)?

(Wicket 1.4,如果重要的话。)

4

3 回答 3

10

如果您希望它可重用,您可以将其定义为IComponentConfigurationBehavior附加到任何容器的(对于 wicket 版本 > 1.4.16),然后在onConfigure()行为方法中设置容器可见性:

class AutoHidingBehavior extends AbstractBehavior {

    @Override
    public void bind(Component component) {
        if (! (component instanceof MarkupContainer) ) {
            throw new IllegalArgumentException("This behavior can only be used with markup containers");
        }
    }

    @Override
    public void onConfigure(Component component) {
        MarkupContainer container = (MarkupContainer) component;
        boolean hasVisibleChildren = false;
        for (Iterator<? extends Component> iter = container.iterator(); iter.hasNext(); ) {
            if ( iter.next().isVisible() ) {
                hasVisibleChildren = true;
                break;
            }
        }
        container.setVisible(hasVisibleChildren);
    }

}
于 2012-08-01T10:00:41.297 回答
4

isVisible如果任何孩子可见(像现在一样评估孩子的可见性),您可以覆盖容器的方法以返回 true。这不会大幅减少代码,但在我看来它会“更好”,因为决定可见性的代码将是它“所属”的地方。你可以把它变成一个专门的容器类来进一步封装代码。

或者您可以继承EnclosureContainer并添加您需要的任何可见性逻辑。

注意:当覆盖 isVisible...

[...]请注意,这有一些陷阱:

  • 每个请求都会多次调用它,可能会调用数十次,因此请保持计算量轻

  • 这个值应该在渲染/响应边界上保持稳定。意思是如果 isVisible() 在渲染按钮时返回 true,但是当单击按钮时返回 false 你会得到一个错误

来自Wicket in Action

于 2012-08-01T08:35:26.553 回答
0

您也可以使用访客。

就我而言,我在面板中有带有链接的容器。代码:

public abstract class MyPanel extends Panel
{
   private final WebMarkupContainer webMarkupContainer;

   public MyPanel(String id)
   {
      super(id);

      webMarkupContainer = new WebMarkupContainer("customContainer")
      {
         @Override
         protected void onBeforeRender()
         {
            super.onBeforeRender();
            boolean visible = Boolean.TRUE.equals(checkVisibleLinks());
            setVisible(visible);
         }
      };

      AjaxLink myLink = new AjaxLink("myLink")
      {
         @Override
         public void onClick(AjaxRequestTarget target)
         {
            //some action
         }

      };

      webMarkupContainer.add(myLink);
   }

   private Boolean checkVisibleLinks()
   {
      return webMarkupContainer.visitChildren(AbstractLink.class, new IVisitor<AbstractLink, Boolean>()
      {
         @Override
         public void component(AbstractLink link, IVisit<Boolean> visit)
         {
            if (link.isVisible())
            {
               visit.dontGoDeeper();
               visit.stop(true);
            }
         }
      });
   }

}
于 2015-03-05T08:27:06.973 回答