Designing Tapestry Mega-Components
Pages: 1, 2
The majority of the DHTML support in Tapestry is provided by the Body component. The Body component replaces the
<body> tag in most Tapestry pages. The Body component provides a number of services to all the Tapestry components it wraps:
<script>block just preceding the
<script>block preceding the
Tapestry Client-Side Scripting
For the Palette component, the associated script takes as input the names assigned to the form and to the Palette component, some flags used to indicate how items are to be sorted (by label, by value, or manually), and the URLs for the various images used on the buttons.
Tapestry script documents have three main sections. In the first section, new symbols are defined, using the
<let> directive. The second section is the
<body> directive, where functions and variables are created. The final section,
Tapestry script documents contain additional directives to accomplish conditional blocks, looping, and inserting symbols.
The Palette script starts by creating a new symbol,
baseName, which combines the name of the form and the name of the Palette component together. All other functions and objects incorporate this base name, which provide a reasonable guarantee that there will not be any name collisions (regardless of the number of forms or Palette components on the page).
<insert property-path="formName"/>_<insert property-path="name"/>
<a> tag for the select button, when that portion of the page's HTML is generated. Now that the name of the function is known, the function itself can be created (within the
<body> section of the Tapestry script):
function <insert property-path="selectFunctionName"/>()
if (<insert property-path="selectDisabled"/>)
var source = <insert property-path="availablePath"/>;
var target = <insert property-path="selectedPath"/>;
var source = document.Form0.inputColor_avail;
var target = document.Form0.inputColor;
This shows how the form name,
Form0, and the Palette name,
inputColor, have been incorporated into the names of the functions and HTML elements.
Like most Tapestry components, the Palette uses an HTML template. The template contains static HTML, which is passed directly back to the client Web browser. Certain portions, marked with tags (including the
jwcid attribute), are placeholders for other components.
<td class="controls" rowspan=2>
<a jwcid="selectButton"><img jwcid="selectImage" alt="[Select]"/></a>
<a jwcid="deselectButton"><img jwcid="deselectImage" alt="[Deselect]"/></a>
For clarity of discussion, the actual HTML template used has been simplified here. Regardless, the template shows that the component produces a table with two buttons and two
For example, the specification for the select button, the button used to move items from the available list to the selected list, is built using two components:
<component id="selectButton" type="Any">
<binding name="href" property-path="symbols.selectOnClickScript"/>
<component id="selectImage" type="Image">
<binding name="image" property-path="selectImage"/>
<binding name="name" property-path="symbols.selectImageName"/>
<component> element identifies the
selectButton component as an
Any component, a type of component that can produce any kind of HTML element. The element binding identifies that the
Any is configured to produce an
<a> tag. This may seem redundant of the HTML template (where it was also shown to be an
<a> tag), but the HTML parser used with Tapestry component templates delibrately ignores the actual tag used -- it is only interested in the structure of the template. The fact that an
<a> tag was used is a convienience for the HTML producer, who'll be able to preview the HTML in a standard editor like HomeSite.
In addition, the
href attribute of the
Any tag is set to the value of a symbol output from the script -- the
selectOnClickScript property discussed earilier. The path,
symbols.selectOnClickScript, means that the
symbols property is obtained from the Palette component, and, within it, the property
selectOnClickScript is extracted. The Palette class is responsible for providing access to the symbol's Map as a read-only JavaBeans property.
Wrapped inside the
selectButton is the
selectImage component, of type
Image. This component generates an HTML
<img> tag. The Palette component provides another property,
selectImage, which identifies the image to be used with the button. The Palette component includes defaults for all the images it needs (for the different buttons and states), but allows any of the images to be overriden, using additional component parameters. The
getSelectImage() method checks for a
selectImage parameter, or provides the default image if the parameter is unspecified.
The client Web browser will see the following HTML for this portion of the Palette:
This same pattern -- defining names of elements and functions, implementing the functions, and linking the HTML elements to those functions -- is followed for all of the other aspects of the Palette component.
Tapestry demonstrates the possibilities for easily assembling complex user interfaces from reusable components. The facilities provided by the framework allow for substantial complexity, easily weaving together both client- and server-side logic with dynamically-generated HTML. Meanwhile, the open source community surrounding Tapestry continues to grow, which means that there will be a bumper crop of these kinds of sophisticated components going forward, a prospect which should delight any Java Web developer.
Howard Ship is an open source Java-based Web developers on several projects, including Tapestry.
Return to ONJava.com.