Components in Templates

Components can be placed anywhere inside a template, simply by adding the jwcid attribute to any existing tag. For example:

Example 2.1. Example HTML template containing components

<html>
  <head>
    <title>Example HTML Template</title>
  </head>
  <body>
    <span jwcid="border">  1
    
      Hello,
      <span jwcid="@Insert" value="ognl:user.name">Joe User</span> 2
    
    </span>
  </body>
</html>	
1

This is a reference to a declared component; the type and parameters of the component are in the page's specification.

2 This is a implicit component; the type of the component is Insert. The value parameter is bound to the OGNL expression user.name.

The point of all this is that the HTML template should preview properly in a WYSIWYG HTML editor. Unlike Velocity or JSPs, there are no strange directives to get in the way of a preview (or necessitate a special editting tool), Tapestry hides what's needed inside existing tags; at worst, it adds a few non-standard attributes (such as jwcid) to tags. This rarely causes a problem with most HTML editors.

Templates may contain components using two different styles. Declared components are little more than a placeholder; the type of the component is defined elsewhere, in the page (or component) specification.

Alternately, an implicit component can be defined in place, by preceding the component type with an "@" symbol. Tapestry includes over forty components with the framework, additional components may be created as part of your application, or may be provided inside a component library.

In the above example, a <span> was used for both components. Tapestry doesn't care what tag is used for a component, as long as the start and end tags for components balance (it doesn't even care if the case of the start tag matches the case of the end tag). The example could just as easily use <div> or <fred>, the rendered page sent back to the client web browser will be the same.

Component Ids

Every component in Tapestry has its own id. In the above example, the first component has the id "border". The second component is anonymous; the framework provides a unique id for the component since one was not supplied in the HTML template. The framework provided id is built from the component's type; this component would have an id of $Insert; other Insert components would have ids $Insert$0, $Insert$1, etc.

A component's id must only be unique within its immediate container. Pages are top-level containers, but components can also contain other components.

Implicit components can also have a specific id, by placing the id in front of the "@" symbol:

  <span jwcid="insert@Insert" value="ognl:user.name">Joe User</span>

The component is still implicit; nothing about the component would go in the specification, but the id of the component would be "insert".

Each component may only appear once in the template. You simply can't use the same component repeatedly ... but you can duplicate a component fairly easily; make the component a declared component, then use the copy-of attribute of the <component> element to create clones of the component with new ids.

Specifying Parameters

Using either style, parameters of the component may be bound by adding attributes to the tag. Most attributes bind static parameters, equivalent to using the <static-binding> element in the specification.

Prefixing an attribute value with ognl: indicates that the value is really an OGNL expression, equivalent to using the <binding> element in the specification.

Finally, prefixing an attribute value with message: indicates that the value is really a key used to get a localized message, equivalent to the <message-binding> element in the specification.

Formal and Informal Parameters

Components may accept two types of parameters: formal and informal. Formal parameters are those defined in the component specification, using the <parameter> element. Informal parameters are additional parameters, beyond those known when the component was created.

The majority of components that accept informal parameters simply emit the informal parameters as additional attributes. Why is that useful? Because it allows you to specify common HTML attributes such as class or id, or JavaScript event handlers, without requiring that each component define each possible HTML attribute (a list which expands all the time).

Informal and formal parameters can be specified in either the specification or in the template. Informal parameters are not limited to literal strings, you may use the ognl: and message: prefixes with them as well.

Not all components allow informal parameters; this is controlled by the allow-informal-parameters attribute of the <component-specification> element. Many components do not map directly to an HTML element, those are the ones that do not allow informal parameters. If a component forbids informal parameters, then any informal parameters in the specification or the template will result in errors, with one exception: static strings in the HTML template are simply ignored when informal parameters are forbidden; they are presumed to be there only to support WYSIWYG preview.

Each component declares a list of reserved names using the <reserved-parameter> element; these are names which are not allowed as informal parameters, because the component generates the named attribute itself, and doesn't want the value it writes to be overriden by an informal parameter. For example, the DirectLink component reserves the name "href" ... putting an href attribute in the HTML template is simply ignored (again, presumed to be there to support WYSIWYG preview). Case is ignored when comparing attribute names to reserved names.