Coding components

When creating a new component by subclassing AbstractComponent, you must write the renderComponent() method. This method is invoked when the components container (typically, but not always, a page) invokes its own renderBody() method.

protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
{
  . . .
}	

The IMarkupWriter object is used to produce output. It contains a number of print() methods that output text (the method is overloaded for different types). It also contains printRaw() methods -- the difference being that print() uses a filter to convert certain characters into HTML entities.

IMarkupWriter also includes methods to simplify creating markup style output: that is, elements with attributes.

For example, to create a <a> link:

writer.begin("a");
writer.attribute("url", url);
writer.attribute("class", styleClass);

renderBody(writer, cycle);

writer.end(); // close the <a>	

The begin() method renders an open tag (the <a>, in this case). The end() method renders the corresponding a. As you can see, writing attributes into the tag is very simple.

The call to renderBody() is used to render this component's body. A component doesn't have to render its body; the standard Image component doesn't render its body (and its component specification indicates that it discards its body). The Conditional component decides whether or not to render its body, and the Foreach component may render its body multiple times.

A component that allows informal parameters can render those as well:

writer.beginEmpty("img");
writer.attribute("src", imageURL);
renderInformalParameters(writer, cycle);

This example will add any informal parameters for the component as additional attributes within the <img> element. These informal parameters can be specified in the page's HTML template, or within the <component> tag of the page's specification. Note the use of the beginEmpty() method, for creating a start tag that is not balanced with an end tag (or a call to the end() method).