6

ブロックレベルの要素であるコンテナがあります。これは、すべての子Wicket要素(ボタン)が非表示になっているときに非表示にする必要があります。つまり、子ボタンが表示されている場合、コンテナが表示されている必要があります。

以前のボタンの1つは、ボタンがある場合は常に表示されていたので、そのボタンを使用しての表示を制御し、<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>

Java:

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

これを再利用可能にする場合は、任意のコンテナーにアタッチする(wicketバージョン> 1.4.16の場合)として定義してから、動作のメソッドでIComponentConfigurationBehaviorコンテナーの可視性を設定できます。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が返される場合、エラーが発生します。

WicketinActionから

于 2012-08-01T08:35:26.553 に答える
0

ビジターも利用できます。

私の場合、Panelにリンクのあるコンテナがあります。コード:

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 に答える