fsilber (5) [Avatar] Offline
The book shows two ways to avoid repeating mark-up that is common to many pages -- mark-up inheritance and panels. The panel example demonstrates panels being replaced dynamically in the same Wicket page object, and says that mark-up inheritance has an advantage when it comes to creating bookmark-able links between pages.

To me, the swapping of panels dynamically is a radically different style of programming that is appropriate only for especially dynamic requirements -- e.g. for creating a desktop-style application that one doesn't think of in terms of pages.

To me, the common-sense way of using panels to create a common look-and-feel in many pages is to create a base page that contains an overridable (and perhaps abstract) "Panel createPanel(String wicket-id){...}" method. The base page calls this method when adding the panel to the page, passing it the panel's wicket:id that is needed for the panel's constructor. The individual pages of the web-app would extend the base page, re-implementing the createPanel() method to produce the panel appropriate to each page. (The wicket:id was passed into the overridable method so that one could later change the panel's wicket:id in the base page without having to change the child pages.)

If you want the individual pages to vary in several ways, the base page would define several such methods to be re-implemented in the child pages.

With this technique, you (1) re-use the base page's mark-up, (2) can vary the individual pages by more than one page section, and (3) have a individually named page class for each web-app you can use in creating bookmark-able links.

/Frank Silbermann
fsilber (5) [Avatar] Offline
Re: Composing pages via panels
I have an addendum to my suggestion above (which was about reusing HTML from a common base page by having the base page define and call a panel-returning method to be overridden in the child pages).

An additional advantage of this approach is that no HTML file whatsoever need be associated with any of the child pages -- the HTML file associated with the panel class definition suffices. The child page relies on its parent's HTML file; all the child page does is implement the method that instantiates-and-returns the panel object. Logic in the base page calls that method and inserts the panel component according to the base page's HTML file.

Indeed, once one has created a base page and an adequate collection of panel subclasses, a whole set of child web pages may be assembled without writing _any_ additional HTML.

Furthermore, one can generalize this technique to produce a whole hierarchy of web pages in which some HTML is shared by all pages, and other HTML is shared only by certain subsets of the concrete child pages.

-- Frank Silbermann
dashorst (107) [Avatar] Offline
Re: Composing pages via panels
The chapter discusses the extremes of page composition and states that you can mix and match them to make your own best fit. There is no one solution that fits all. By discussing the extremes and showing what the advantages and disadvantages are, people can make their own choices.
fsilber (5) [Avatar] Offline
Re: Composing pages via panels
> The chapter discusses the extremes of page composition and
> states that you can mix and match them to make your own best fit.

Yes, of course. However, my suggestion is not really a mix-and-match (I don't use wicket:child or wicket:extend at all). It's just a different way of using panels. I guess specifying of the child page's panel by overriding a method called by the parent's page constructor will seem trivially obvious to those who are comfortable with object orientation.
fsilber (5) [Avatar] Offline
Re: Composing pages via panels
In a discussion blog (http://blog.jteam.nl/2009/09/16/wicket-dos-and-donts/) Erik van Oosten explained that my approach to page assembly (described above some months ago) was a bad idea -- because base class constructors should not call abstract methods. (They execute before the subclass constructor has completed. I usually got away with this, but I was burnt a few times when method implementations accessed properties not yet initialized by the subclass' constructor.)

However, I do like the idea of using abstract Panel-creating methods in the base page to tell the sub-page developer what panels need to be added (with the base page passing in the needed wicket-id as a parameter). This approach obviates any need for an HTML file associated with the sub-page, and it allows multiple locations in the base-page for the subclass to fill in. I thought of what seems to be a simple fix for the constructor-calls-overridable-method problem:

(1) Move the base page’s component tree construction out of the constructor into the method:

... private void assembleComponents() { …

(2) Add the property:

. private boolean componentsAssembled = false;

(3) Override as follows to construct the component tree after the class constructors finish:

...void onBeforeRender() {
......if ( !componentsAssembled ) {
............componentsAssembled = true;
......super.onBeforeRender(); // Or whatever else, if anything, I might otherwise have put into this method

Then component construction would wait until the properties in both the parent and the subclass had been set, so I’d no longer have a problem with calling abstract methods from the constructor.

Do you see any disadvantages to this approach? Is there a more appropriate hook upon which to hang my base page's component-tree assembly?

If it is a good approach, I wonder why the Wicket designers did not create an overrideable called-once-after-constructors method in the Component class, and tell developers that this is where the component tree should be created.