Saturday, 31 March 2012

Page Rendering

Pages are asked to render themselves only by IRequestTargets (see Request targets). So the initial message renderPage() comes from a target instance. Page render initiates render of all its subcomponents and is responsible for calling render related methods. Since page extends MarkupContainer most of its render logic is applicable to any MarkupContainer. Page rendering consists of the following steps:
  • before render step
  • rendering
  • after render step
It worth mentioning that before those steps page restores values of all form components which can be persisted (see FormComponent#supportsPersistence()). These values can be restored from anywhere (see IValuePersister interface). By default they are restored from cookies.
The renderNext() method belongs to MarkupContainer class and it is not used exclusively by pages. This method gets current tag from markup stream and attempts to find component which current markup tag corresponds to. Finding a component includes:
  • attempt to get component by id (value from "wicket:id" attribute) from the current markup container which is in case of rendering a page is page
  • attempt to find among parent markup containers the one that implements IComponentResolver interface and that can handle the current tag. This is used for example by Border component to resolve <wicket:body/> tag. In case of rendering a page there is no parent containers.
  • attempt to find IComponentResolver implementation registered at application level which can handle the current tag. These implementations include instances that handles all built-in wicket tags such as <wicket:extend>, <wicket:message> and others. You can add your implementation of IComponentResolver using Settings#addComponentResolver() method.
If component is found, it is asked to render itself by calling Component#render(MarkupStream) method (see Component rendering). Otherwise exception if thrown with a messages like "Unable to find component with id ... This means that you declared wicket:id ... in your markup, but that you either did not add the component to your page at all, or that the hierarchy does not match".
You should not change component state or change model during this step.

After render

After render step is similar to before render step. It includes:
  • calling onAfterRender() method for every component on the page
  • notifying all registered instances of IComponentOnAfterRenderListener (you can register a listener using Application#addComponentOnAfterRenderListener() method)
Unlike before render step these actions will be applied for all components whether there are visible or not. As a MarkupContainer page calls MarkupContainer#onAfterRenderChildren() and process all of its immediate subcomponents.
You should not change component state or change model during this step.

No comments:

Post a Comment