Previous Next vertical dots separating previous/next from contents/index/pdf

Tag Library Customization

It is now possible to customize many aspects of JSP tag libraries using simple, powerful metadata files. Most notable is the ability to write Velocity HTML rendering templates to customize the rendering of JSP tags and JSF components in the JSP design editor.

This topic contains the following sections:

Overview

Workshop Studio products integrate many of the standard tag libraries (HTML, JSP, JSTL, Struts, JSF etc). This integration allows the IDE to control things like:

This topic shows you how to customize the IDE for other JSP tag libraries and JSF components. Tag libraries customization is specified in an xml-format Tag Library Extra Information (tlei) file that should meet the following requirements:

For example, you might customize the tag library "/WEB-INF/app.tld" in the file "/WEB-INF/app.tlei" or "/WEB-INF/nitrox/app.tlei".

An example of a tlei file follows:

<tlei>
  <css-uri>app.css</css-uri>

  <tag name="myTag">
    <display-name>My Tag</display-name>

    <small-icon>images/myTag.gif</small-icon>

    <!-- render the tag as 3 text fields separated by / -->
    <rendering-template><![CDATA[
      <input type="text" name="month" size="2"/>
      / <input type="text" name="day" size="2"/>
      / <input type="text" name="year" size="4"/>
    ]]></rendering-template>

    <attribute name="myAttr">
      <sub-type>uri</sub-type>
    </attribute>
  </tag>
</tlei>

The following sections describe the various tlei tags.

Tag Rendering

Tag rendering controls how a tag is presented in the JSP editor's Design view. By default the editor renders a custom tag as a framed box containing the tag icon and name. Tag rendering can be customized in the tlei file as follows:

Rendering Label

By default the design editor renders a custom tag as a framed box containing the tag icon and the tag prefix:name as a label. You can customize this label by using the rendering-label tag.

The rendering-label tag can contain any text mixed with any of the following special expressions which are evaluated dynamically:

For example:

<tlei>
  <tag name="myTag">
    <rendering-label>${tag.fullName} (${tag.attr.page})</rendering-label>
  </tag>
</tlei>

Rendering Templates

You can specify a Velocity template to be used as the rendering JSP source code. In general, the template contains arbitrary HTML/JSP along with Velocity expressions for conditional/iterative content. You do not need extensive Velocity experience to write a rendering template, the examples in this section will show you many common cases. For more advanced Velocity usage consult the Velocity User Guide. Note that the template does not necessarily need to have Velocity expressions. For example if the tag represents a date, and you want it to be rendered as 3 edit fields regardless, then you can specify it as follows:

<tlei>
  <tag name="myTag">
    <rendering-template><![CDATA[
      <input type="text" name="month" size="2"/>
      / <input type="text" name="day" size="2"/>
      / <input type="text" name="year" size="4"/>
    ]]></rendering-template>
  </tag>
</tlei>

Note that the template content should to be enclosed in <![CDATA[ and ]]> so that the xml parsing does not get confused by the html tags! If the tag rendering depends on the tag body content and/or tag attribute values then you can use the Velocity context variable tag to access these values. Usually you'll use one or more of the following Velocity expressions to access the underlying tag information:
  • ${tag.name}: Evaluates to the tag name. For example:
    <tlei>
      <tag name="myTag">
        <rendering-template><![CDATA[
          <span style="color: red">${tag.name}</span>
        ]]></rendering-template>
      </tag>
    </tlei>
    renders as the tag name in red.  
  • ${tag.fullName}: Evaluates to the tag prefix and tag name (for example h:commandView).  
  • ${tag.displayName}: Evaluates to the tag display name specified in the tlei file using the display-name tag. If no display name is specified then the tag name is used.  
  • ${tag.missingAttr("attrName")}: A boolean expression evaluating to true if the tag does not have the given attribute.  
  • ${tag.attr("attrName")}: Evaluates to the attribute value of the attribute named attrName. Evaluates to an empty string if the tag does not have the given attribute. For example:
    <tlei>
      <tag name="myTag">
        <rendering-template><![CDATA[
          #if (!$tag.missingAttr("attr1"))
            ${tag.attr("attr1")}
          #else
            ${tag.attr("attr2")}
          #end
        ]]></rendering-template>
      </tag>
    </tlei>
    renders the value of the attribute attr1 unless it is not specified in the tag where it renders the value of the attribute attr2.  
  • ${tag.attrInt("attrName")}: Same as ${tag.attr("attrName")} but converts the value to an integer. Evaluates to 0 if the tag does not have the given attribute, or if the value cannot be converted to integer. This could be used in some cases to generate iterative content based on a tag attribute value.  
  • ${tag.empty}: A boolean expression evaluating to true if the tag does not have any children (i.e no body content).  
  • ${tag.childrenTags}: Evaluates to the list of children tags, empty list if none. You would usually iterate the returned list and use the iteration variable as a tag variable. For example:
    <tlei>
      <tag name="myTag">
        <rendering-template><![CDATA[
          #set ($count = 0)
          #foreach ($childTag in $tag.childrenTags)
            #if (${childTag.name} == "myOtherTag")
              #set ($count = $count + 1)
            #end
          #end
          Found ${count} myOtherTag tags.
        ]]></rendering-template>
      </tag>
    </tlei>
    renders the count of children tags having a specific name.  
  • ${tag.childrenSource}: Evaluates to the JSP source code of the tag's children, or empty string if none (i.e if the tag does not have any children). For example, a tree node tag could be rendered as follows:
    <tlei>
      <tag name="myTag">
        <rendering-template><![CDATA[
          ${tag.attr("label")}
          #if (!${tag.empty})
            <div style="margin-left: 30">${tag.childrenSource}</div>
          #end
        ]]></rendering-template>
      </tag>
    </tlei>
    It renders the node label, then renders the children nodes (if any) indented. Note that in this example, nested children tree nodes tags are rendered recursively using the same markup templates!  
  • ${tag.childTag(name, prefix, attrName, attrValue)}: Evaluates to the first child tag matching the given tag name, tag prefix and attribute name/value. For example:
    <tlei>
      <tag name="myTag">
        <rendering-template><![CDATA[
          #set ($header = $tag.childTag("facet", "f", "name", "header"))
          #if ($header) Found header facet: ${header.childrenSource}
          #else Header facet not found!
          #end
        ]]></rendering-template>
      </tag>
    </tlei>
    renders the content of the nested f:facet tag having a name equals to header, or an error message if not found.  
  • ${tag.childTag(name, prefix)}: Evaluates to the first child tag matching the given tag name and tag prefix (regardless of any attribute value).  
  • ${tag.url("uri")}: Evaluates to the absolute url corresponding to the given relative uri. The uri should be relative to the location of the file containing the template (i.e relative to the tlei file if you are using the rendering-template tag, or relative to the template file if you are using the rendering-template-uri tag as described later). Usually you use the url function if your template contains images to compute the image source so that the editor can find them. For example:
    <tlei>
      <tag name="myTag">
        <rendering-template><![CDATA[
          <img src="${tag.url("images/myImage.gif")}"/>
          <input type="text" name="" size="20"/>     ]]></rendering-template>
      </tag>
    </tlei>
    renders an image and a text input field. Note that in this example the image myImage.gif should be located in a folder named images which should be present in the same directory as the tlei file (where the template is specified).  
  • ${tag.icon}: Evaluates to the absolute url of the tag icon specified in the tlei file using the small-icon tag.

Rendering Template Files

You can specify a rendering template in its own file using the rendering-template-uri tag. This is usually used if the rendering template is shared between multiple tags, or if it is large. The template file should be specified relative to the location of the tlei file. It could have any name and any file extension. For example:

<tlei>
  <tag name="myTag">
    <rendering-template-uri>templates/myTag.vm</rendering-template-uri>
  </tag>
</tlei>

Note that in this example the file myTag.vm should be located in a folder named templates which should be present in the same directory as the tlei file. Of course when you use a separate template file the <rendering-template> and <![CDATA[ are not needed!

Rendering Template Examples

Following are examples of how the IDE uses the rendering templates for some of the MyFaces JSF components:

x:commandNavigation

<a href="#">${tag.attr("value")}</a>
#if (!$tag.empty)
  <div style="margin-left: 16">${tag.childrenSource}</div>
#end

x:inputDate

#set ($type = ${tag.attr("type")})
#set ($styleClass = ${tag.attr("styleClass")})
#set ($style = ${tag.attr("style")})

#if (!($type == "time"))
<input type="text" name="day" size="8" class="$styleClass" style="$style"/> <select name="month" class="$styleClass" style="$style"/> <input type="text" name="year" size="10" class="$styleClass" style="$style"/> #if (${tag.attr("popupCalendar")} == "true") <input type="button" value="..."/> #end #end
#if ($type == "both" || $type == "time")
<input type="text" name="hour" size="10" class="$styleClass" style="$style"/> :<input type="text" name="minute" size="10" class="$styleClass" style="$style"/> :<input type="text" name="second" size="10" class="$styleClass" style="$style"/>
#end

x:dataScroller

#if (${tag.attr("renderAsPopup")} == "true")
<input type="text" name="${tag.attr("value")}" class="${tag.attr("styleClass")}" style="${tag.attr("style")}"/> <input type="button" value="..."/>
#else
<table class="${tag.attr("styleClass")}" style="${tag.attr("style")}>
<tr class="${tag.attr("monthYearRowClass")}">
<td><a href="#"><</a></td>
<td colspan="5">Month Year</td>
<td><a href="#">></a></td>
</tr> <tr class="${tag.attr("weekRowClass")}">
<td>Sun</td>
<td>Mon</td>
<td>Tue</td>
<td>Wed</td>
<td>Thu</td>
<td>Fri</td>
<td>Sat</td>
</tr> #foreach ($i in [0..4])
<tr>
#foreach ($j in [0..6])
#set ($day = $i * 7 + $j)
#if ($day <= 0)
<td class="${tag.attr("dayCellClass")}"></td>
#elseif ($day == 7)
<td class="${tag.attr("currentDayCellClass")}"><a href="#">$day</a></td>
#elseif ($day <= 31)
<td class="${tag.attr("dayCellClass")}"><a href="#">$day</a></td>
#end
#end
</tr>
#end
</table>
#end

x:dataScroller

#macro (facet $facetName)
#if ($tag.childTag("facet", "f", "name", $facetName))
<td>
#set ($facetTag = $tag.childTag("facet", "f", "name", $facetName))
<a href="#">$facetTag.childrenSource</a>
</td>
#end
#end <table><tr>
#facet("first")
#facet("fastrewind")
#facet("previous") #if ($tag.attr("paginator") == "true")
<td> <table cellpadding="1" cellspacing="1" class="${tag.attr("paginatorTableClass")}" style="${tag.attr("paginatorTableStyle")}"><tr>
#set ($max = $tag.attrInt("paginatorMaxPages"))
#if ($max < 2)
#set ($max = 2)
#end
<td class="${tag.attr("paginatorActiveColumnClass")}" style="${tag.attr("paginatorActiveColumnStyle")}">
<a href="#">1</a>
</td>
#foreach ($i in [2..$max])
<td class="${tag.attr("paginatorColumnClass")}" style="${tag.attr("paginatorColumnStyle")}">
<a href="#">$i</a>
</td>
#end
</tr></table> </td>
#end #facet("next")
#facet("fastforward")
#facet("last")
</tr></table> #foreach ($child in $tag.childrenTags)
#if (!($child.name == "facet"))
$child.source
#end
#end

CSS File

You can associate standard css styles to any of the tag library tags. The css styles are declared in a css file specified using the tlei tag css-uri. The css file is specified relative to the tlei file location. For example, if you want the tag myTag to be rendered in green with a red border, then first you specify the css file as follows:

<tlei>
  <css-uri>app.css</css-uri>
</tlei>
Then add the line: myTag {color: green; border: 1 solid red} to the app.css file. Note that in this example the file app.css should be located in the same directory as the tlei file. Usually you would need a CSS file in the following cases:
  • The tag is rendered using the rendering-label tag, and you want the label to appear using a special style.  
  • If you are using a rendering template then you normally do not need to specify a css style in the tag library css file as you can specify it in the template itself (using a span tag for example). The only case where you would need to associate a css style is when you want the tag to be rendered in its own line (i.e if no other tags are to be rendered in the same line). In this case you should specify the following css style in the tag library css file: myTag {display: block}

Tag Attributes

Tag attributes can be customized in the tlei file by specifying sub types and enumerations. There are 2 tlei tags for attribute customization:

  • attribute: You can customize a specific tag attribute as follows:
    <tlei>
      <tag name="myTag">
        <attribute name="myAttr">
          <enumeration>value1, value2</enumeration>
        </attribute>
      </tag>
    </tlei>
    This example associates an enumeration to the attribute myAttr of the tag myTag.  
  • global-attribute: You customize all attributes having a given name using the global-attribute tag. For example:
    <tlei>
      <global-attribute name="action">
        <sub-type>jsf-action</sub-type>
      </global-attribute>
    </tlei>
    Says that an attribute named action in any tag in the tag library should have the jsf-action sub type. This is just a shortcut of using the attribute tag for all the action attributes. The IDE predefined attribute sub types are discussed below.

Attribute Sub Type

The IDE predefines attribute sub types that makes it smarter when dealing with the attribute values in the areas of attribute value editing, attribute value navigation, page validation and consistency checking, and AppXRay dependencies. For example, by specifying the struts-action-mapping sub type for an attribute, the IDE would automatically:

  • Include a custom attribute editor in the Smart Editor or Property Sheet that shows the Struts actions available to the current page.
  • Propose the list of Struts actions for source code completion.
  • Navigate to the action definition from the source code (control-click), or from the tag's Smart Editor.
  • Report an error when an invalid Struts action is used as a value in the corresponding attribute.
  • Show the dependency from the page containing the attribute value to the Struts action in AppXaminer.

Following are the predefined sub types along with the description of their corresponding attribute values:

  • color: A color. For example "red" or "#00993F"
  • field-name: A variable field/property name. This is usually used when another attribute in the same tag has the var-name sub type.
  • jsf-action: A JSF action. Navigation outcomes and method binding bindings are supported.
  • jsf-action-listener: A JSF action listener.
  • jsf-validator: A JSF validator.
  • jsf-value-listener: A JSF value listener.
  • type: A Java class name.
  • struts-action-forward: A Struts action forward name.
  • struts-action-mapping: A Struts action mapping name.
  • struts-uri: A Struts uri (action, page or tile).
  • style: A CSS style. For example "color: chocolate; font-size: small"
  • style-class: A CSS style class name.
  • uri: A file uri relative to the containing page.
  • var-name: A variable name. Only variables accessible to the containing tag are available.

Note that the "struts-xxx" sub types are enabled only for Workshop Studio and Workshop for Struts, and the "jsf-xxx" sub types are enabled only for Workshop Studio and Workshop for JSF.

Attribute Enumeration

You can specify that an attribute value is limited to a predefined set of values by using the enumeration tag. For example:

<tlei>
  <tag name="myTag">
    <attribute name="myAttr">
      <enumeration>value1, value2</enumeration>
    </attribute>
  </tag>
</tlei>

The IDE would automatically:

  • Include a combo box attribute editor in the Smart Editor and Property Sheet that shows the enumeration values.
  • Propose the enumeration values for source code completion.
  • Report an error when a value not in the enumeration is used.

Tag Editors

When a custom tag is edited in the design or source editors, the IDE by default shows a standard property sheet that allows modifying the tag attribute values. In many cases, especially for richer JSF components, the number of attributes is large and one would want to have a more optimized way to edit the "frequently used" attributes. You can do just that by defining a custom tag editor. Using metadata you specify what attributes to be shown and how they are grouped. The metadata is then used to present in the dialog-like Smart Editor ui along with the property sheet. In general, the tag editing dialog consists of editors for the attributes you specify in the metadata file. Each attribute editor consists of its editing control (a text field, combobox etc) along with a custom editing button added based on the attribute sub type if any (as described in the Tag Attributes section).

The tag editing metadata is specified in a .tagedit file that you specify in the tlei file using the tag-edit-uri tag. As always the .tagedit file is specified relative to the tlei file location. For example:

<tlei>
  <tag name="myTag">
    <tag-edit-uri>tagedit/myTag.tagedit</tag-edit-uri>
  </tag>
</tlei>

An example of a .tagedit file follows:

<tag-edit>
  <dialog-info kind="insert-modify">
     <field-group>
      <field name="value">
        <display-name>Value</display-name>

        <bind-info source-kind="any"/>
      </field>

      <field name="converter">
        <display-name>Converter</display-name>
      </field>
     </field-group>

     <field-group>
      <label>CSS Properties</label>

      <field name="styleClass">
        <display-name>CSS Class</display-name>
      </field>

      <field name="style">
        <display-name>CSS Style</display-name>
      </field>
     </field-group>
  </dialog-info>
</tag-edit>

Here are the description of the main tags:

dialog-info: Contains the editor's field groups and fields. The required kind attribute should have one of the following values:

  • insert-modify: The editor is used for both tag insertion and modification.
  • insert: The editor is used only for tag insertion (from the Tag Libraries View).
  • modify: The editor is used only for tag modification.

You can have multiple dialog-info tags with different kind attributes if necessary.

field-group: Groups the related tag attributes. The field tag can have any of the following optional child tags:

  • label: Used as the group label. If not specified then the tag display name followed by the string "Properties" is used.

field: Specifies the tag attribute to be added to the dialog. The required name xml attribute contains the tag attribute name. The field tag can have any of the following optional child tags:

  • display-name: Used as the editing control label. If missing then the attribute name is used.  
  • default-value: The attribute default value. The value you specify is rendered in the editor's control with a special text style when the attribute value is null. For example: <field name="scope"> <default-value>page</default-value> </field>  
  • initial-value: The initial value of the attribute editor control. The value you specify is used to initialize the editor's control when the tag is being inserted. For example: <field name="myAttr"> <initial-value>Initial Value</initial-value> </field>  
  • bind-info: If present then a data binding button is added allowing the user to bind the attribute value to a page variable or a resource bundle key. The optional source-kind attribute controls the binding possibilities, the default is any:
    • valref: Only value references (variables or variables fields) are allowed.
    • resource: Only resource bundle keys are allowed.
    • any: Both value references and resource keys are allowed.

Tag Formatting

You can control how a tag is formatted in the source code using the format tlei tag. Tag formatting controls whether line feeds are inserted before/after a tag/end tag, and how a tag body is indented and line-wrapped. The rules you specify in the tlei file takes effect when a tag is formatted, for example when tags are inserted using the Tag Libraries View.

For example:

<tlei>
  <tag name="myTag">
    <format line-break="before-after" content-format="wrap-indent"/>
  </tag>
</tlei>

Both the line-break and the content-format attributes are required.

The possible values for the line-break attribute:

  • before-after: A line break is inserted before the start tag and after the end tag.
  • before-inside-after: A line break is inserted before the start tag, after the start tag, before the end tag and after the end tag.
  • after: A line break is inserted after the end tag (or after the start tag if the tag is empty).
  • none: No line breaks are inserted for the tag.

The possible values for the content-format attribute:

  • wrap: The tag content is line-wrapped but not indented.
  • wrap-indent: The tag content is line-wrapped and indented.
  • none: The tag content is not line-wrapped nor indented.

Tag Libraries View

The following tlei tags can be used to customize how the tags are presented in the Tag Libraries View:

  • display-name: The value is used as the tag label displayed in the Tag Libraries View. Note that this can also be specified in the tld file using the display-name tag. The display-name tag is also used to specify a label for the tag library itself.  
  • small-icon: A uri to an image file. The uri is specified relative to the tlei file. The icon is displayed in the Tag Libraries View along with the display name.
     
  • description: The value is used in the tool tip shown when the mouse is over a tag in the Tag Libraries view. Note that this can also be specified in the tld file using the description tag.
    The description tag is also used to specify a description for the tag library itself.

For example:

<tlei>
  <display-name>My Tag Library</display-name>

  <description>The description of the tag library.</description>

  <tag name="myTag">
    <display-name>My Tag</display-name>

    <description>The description of my tag.</description>

    <small-icon>images/myTag.gif</small-icon>
  </tag>
</tlei>

Specifying that a Tag Library Contains JSF Components

Knowing that a tag library contains JSF components is very useful, for example, when deciding whether to enable JSF expressions and method binding for the attribute values.

You can specify that a tag library contains JSF components by using the property tlei tag using jsf as the name, and true as the value. For example:

<tlei>
  <property name="jsf" value="true"/>
</tlei>

 

 

Skip navigation bar   Back to Top