views:

108

answers:

3

Is it possible to implement some kind of decorator component in wicket ? Specially while honoring the id of the decorated component ?

Currently i try to solve this using a Border Component acting as a decorator:

Given:

public XXXPage()
{
   MyBorder border = new MyBorder("xxx");
   border.add( new Label("xxx", "Foo") ); // label just as simplification. Its really a Component that we want to surround the anchor (linkify) around.
   add(border);
} 

XXXPage.html

<body>
<span wicket:id="xxx"/>
</body>

MyBorder.html

<wicket:border>
<a wicket:id="link"><wicket:body/></a>
</wicket:border>

MyBorder.java

public MyBorder(String id)
{
    super(id);
    AjaxLink link = new AjaxLink("link")
    {
       @Override public void onClick(AjaxRequestTarget arg0)
      {
      }
    };
add(link);
link.add(getBodyContainer()); // from javadoc of Wicket's Border
}

Gives:

org.apache.wicket.WicketRuntimeException: The component(s) below failed to render. A     common problem is that you have added a component in code but forgot to reference it in the markup (thus the component will never be rendered).

1. [Component id = xxx]
at org.apache.wicket.Page.checkRendering(Page.java:1182)

So in essence, the xxx component should be wrapped in a transparent manner with a link component. This xxx is out of control.

In a "banana wicket" implementation this would be a possible pseudo code:

Component wrapWithAction(Component a) {
// now wrap
    Link b = new Link() {
     // handle link onClick and all that
    }
    b.wrap(a);
    return b;
}
// 
+1  A: 

I think you'd have better luck adding either a WebMarkupContainer or Fragment within your ListView than anything else.. These two can both contain other Components such as Links, Labels, etc..

Let me know if you need more help..

Tim
Thanks, tim. I changed the question to really point to the core question. In essence, have a look at the last code snipped that shows the pseudo code which basically needs to be translated into wicket api.
Toni Menzel
thanks. Actually the real decorator approach i planned to do does not work. However, i now just have the markup with a surrounding border and the "item" itself. In cases where i dont want to add the link i just use a WebMarkupContainer.Works. thx
Toni Menzel
Glad to hear this nudged you towards a solution, sorry I couldn't check back to help earlier..
Tim
A: 

Add an AjaxEventBehavior for "onclick" to the Component. The example in the Javadoc I linked does what you want.

You can add Behaviors to almost anything in Wicket, that's one of its most powerful features.

Thomas Kappler
Thanks, Thomas. Unfortunately then i cannot add the surrounding anchor in the markup which is essential for me.. :(
Toni Menzel
Maybe you could use a generic WebMarkupContainer or something like that to put the link into, if you need a Component? Then you can attach the behavior to that. But I don't see why you'd need an extra anchor. By attaching the behavior to the original component, you don't need to do the substituting components thing.
Thomas Kappler
Thomas, the Component we wrap is usually annotated text, so an anchor (<a>) in html is used to mark that as link both for semantic and styleability (css) reasons.
Toni Menzel
A: 

Depends on what kind of stuff your decorator wants to do. The regular meaning of decorating is to have object B assume the role of object A, providing exactly the same contract, using A to implement that contract, but do something extra on top of that. I think that that's not a very common case with Widgets. Rather you are looking to reuse some part (the UI and state, maybe behavior). In general, in my opinion, this works best through using panels and markup inheritance.

Technically, borders are the out-of-the-box reusable solution for decorating, but in practice they prove to be a bit hairy to work with. For relatively straightforward way of doing simple decorations, see my answer on http://stackoverflow.com/questions/3933921/generating-commented-out-content-with-wicket/ (which uses the somewhat undocumented way Wicket's rendering pipeline works). Also shows that Wicket's behaviors are a very flexible way to modify behavior of existing components without requiring those components themselves to be changed. Other than that, I would just design for reuse explicitly.

Eelco

related questions