Replacing page elements
Replacing elements of the page is the most powerful general-purpose way to customize the look-n-feel of the viewer. Examples include the Fullcalendar, Tabular Download and PDF.js components.
The pages generated by Apache Causeway' Wicket viewer are built up of numerous elements, from fine-grained widgets for property/parameter fields, to much larger components that take responsibility for rendering an entire entity, or a collection of entities.
Under the covers these are all implementations of the the Apache Wicket Component
API.
The larger components delegate to the smaller, of course.
How the viewer selects components
Components are created using Apache Causeway' ComponentFactory
interface, which are registered in turn through the ComponentFactoryRegistrar
interface.
Every component is categorizes by type (the ComponentType
enum), and Apache Causeway uses this to determine which ComponentFactory
to use.
For example, the ComponentType.BOOKMARKED_PAGES
is used to locate the ComponentFactory
that will build the bookmarked pages panel.
Each factory is also handed a model (an implementation of org.apache.wicket.IModel
) appropriate to its ComponentType
; this holds the data to be rendered.
For example, ComponentType.BOOKMARKED_PAGES
is given a BookmarkedPagesModel
, while ComponentType.SCALAR_NAME_AND_VALUE
factories are provided a model of type of type ScalarModel
.
In some cases there are several factories for a given ComponentType
; this is most notably the case for ComponentType.SCALAR_NAME_AND_VALUE
.
After doing a first pass selection of candidate factories by ComponentType
, each factory is then asked if it appliesTo(Model)
.
This is an opportunity for the factory to check the model itself to see if the data within it is of the appropriate type.
Thus, the BooleanPanelFactory
checks that the ScalarModel
holds a boolean, while the JodaLocalDatePanelFactory
checks to see if it holds org.joda.time.LocalDate
.
There will typically be only one ComponentFactory
capable of rendering a particular ComponentType
/ScalarModel
combination; at any rate, the framework stops as soon as one is found.
There is one refinement to the above algorithm where multiple component factories might be used to render an object; this is discussed in Additional Views of Collections, below. |
How to replace a component
This design (the chain of responsibility design pattern) makes it quite straightforward to change the rendering of any element of the page. For example, you might switch out Apache Causeway' sliding bookmark panel and replace it with one that presents the bookmarks in some different fashion.
First, you need to write a ComponentFactory
and corresponding Component
.
The recommended approach is to start with the source of the Component
you want to switch out.
The ComponentFactory
should be annotated as a Spring service, typically using Spring’s @Service annotation.
For example:
import org.springframework.stereotype.Service;
@Service
public class MyBookmarkedPagesPanelFactory extends ComponentFactoryAbstract {
public MyBookmarkedPagesPanelFactory() {
super(ComponentType.BOOKMARKED_PAGES);
}
@Override
public ApplicationAdvice appliesTo(final IModel<?> model) {
return appliesIf(model instanceof BookmarkedPagesModel);
}
@Override
public Component createComponent(final String id, final IModel<?> model) {
final BookmarkedPagesModel bookmarkedPagesModel = (BookmarkedPagesModel) model;
return new MyBookmarkedPagesPanel(id, bookmarkedPagesModel);
}
}
and
public class MyBookmarkedPagesPanel
extends PanelAbstract<BookmarkedPagesModel> {
...
}
Here PanelAbstract
ultimately inherits from org.apache.wicket.Component
.
Your new Component
uses the information in the provided model (eg BookmarkedPagesModel
) to know what to render.
Your new component will be used instead of the default implementation.
Additional Views of Collections
As explained above, in most cases Apache Causeway' Wicket viewer will search for the first ComponentFactory
that can render an element, and use it.
In the case of (either standalone or parented) collections, though, the viewer will show all available views.
For example, out-of-the-box Apache Causeway provides a table view, a summary view (totals/sums/averages of any data), and a collapsed view. These are selected by clicking on the toolbar by each collection.
Additional views though could render the objects in the collection as a variety of ways; as illustrated by the PDF.js, Fullcalendar and Tabular Download extensions.
Wicket itself has lots of components available at its wicketstuff.org companion website; you might find some of these useful for your own customizations.
Custom object view (eg dashboard)
One further use case in particular is worth highlighting; the rendering of an entire entity.
Normally for entities this is done using Bs3GridPanelFactory
, this being the first ComponentFactory
for the ComponentType.ENTITY
that is registered in Apache Causeway default ComponentFactoryRegistrarDefault
.
You could, though, register your own ComponentFactory
for entities that is targeted at a particular class of entity - some sort of object representing a dashboard, for example.
It can use the EntityModel
provided to it to determine the class of the entity, checking if it is of the appropriate type.
The reference app includes an example of this technique (Featured > Where in the World
).