Tuesday, May 20, 2008

HTML Tag Template - Tag File

     Now that we've done the Java part, let's get down to Tag File. First of all, we need to add value, input, and select functions from the Utility class to a tld file and place it under WEB-INF.

html.tld

<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>HTMLFunc</short-name>
<function>
<name>value</name>
<function-class>net.yw.html.HTMLTagUtils</function-class>
<function-signature>java.lang.String value(java.lang.Object, java.lang.String, boolean)</function-signature>
</function>
<function>
<name>input</name>
<function-class>net.yw.html.HTMLTagUtils</function-class>
<function-signature>java.lang.String input(java.lang.Object, java.lang.String, java.lang.String, java.lang.String, java.util.Map)</function-signature>
</function>
<function>
<name>select</name>
<function-class>net.yw.html.HTMLTagUtils</function-class>
<function-signature>java.lang.String select(java.lang.Object, java.lang.String, java.lang.String, java.util.Map, java.lang.Object, java.lang.String, java.lang.String, java.lang.String)</function-signature>
</function>
</taglib>


     Also, you'll need to create a tags folder under WEB-INF which will holds all the tag files. In addition, an include.jsp which holds all the tag definition is imported in each tag file.

includes.jsp

<%--  To use Servlet 2.4, the following setting should have a "/jsp" before "/jstl" --%>
<%-- JSTL Tags --%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn"  uri="http://java.sun.com/jsp/jstl/functions" %>

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

<%-- Other Tags --%>
<%@ taglib uri="/WEB-INF/html.tld" prefix="html" %>
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags"%>


     Assume that form and error information is hold in request, and a default error style -- 'errorField' exists, we now have two standard tag files.

input.tag

<%@ tag dynamic-attributes="attrMap" %>
<%@ attribute name="type" required="true" rtexprvalue="true" %>
<%@ attribute name="property" required="true" rtexprvalue="true" %>
<%@ attribute name="styleClass" required="false" rtexprvalue="true" %>
<%@ attribute name="errorStyleClass" required="false" rtexprvalue="true" %>

<%@ include file="/WEB-INF/jsp/common/includes.jsp"%>

<c:set var="type" value="${fn:toLowerCase(type)}"/>
<c:set var="class" value="${styleClass == null ? 'right-align' : styleClass}"/>
<c:if test="${not empty request.errors.messages[property]}">
<c:set var="class" value="${errorStyleClass == null ? 'errorField' : errorStyleClass}"/>
</c:if>
${html:input(request.form, property, class, type, attrMap)}


select.tag

<%@ tag dynamic-attributes="attrMap" %>
<%@ attribute name="property" required="true" rtexprvalue="true" %>
<%@ attribute name="collections" required="false" rtexprvalue="true" type="java.lang.Object"%>
<%@ attribute name="valueProperty" required="false" rtexprvalue="true" %>
<%@ attribute name="labelProperty" required="false" rtexprvalue="true" %>
<%@ attribute name="styleClass" required="false" rtexprvalue="true" %>
<%@ attribute name="errorStyleClass" required="false" rtexprvalue="true" %>

<%@ include file="/WEB-INF/jsp/common/includes.jsp"%>

<c:set var="class" value="${styleClass == null ? '' : styleClass}"/>
<c:if test="${not empty request.errors.messages[property]}">
<c:set var="class" value="${errorStyleClass == null ? 'errorField' : errorStyleClass}"/>
</c:if>
<c:set var="optionString"><jsp:doBody /></c:set>
${html:select(request.form, property, class, attrMap, collections, valueProperty, labelProperty, optionString)}


     Note there is an attribute called attrMap which is a dynamic-attribute. With attrMap in place, you can add any extra attribute to the tag besides what have been defined in the tag file. And these extra attributes will be passed as the HTML Tag's atrribute values. It is safe to do so as long as the property filter process in FormTagTemplate.java is in place.

     For select tag, the user has multiple ways to specify options. You can write the options manually between the select tag. Or, you can pass in a collection or an array and specify the value and label property. Also, you can pass in a map which's key is the value property and value is the label property. There is also a blank option indicating adding a blank option on top of the option list when it's true.

     Here is some example:

<tags:input type="text" property="stockNumber" size="29" styleClass="left-align" tabindex="1" errorStyleClass="errorClass" maxlength="20"/>

<tags:select property="typeId" collections="${request.form.optionMap}" blank="true" tabindex="2" />

<tags:select property="selectedName" style="width: 80px" onchange="javascript:doSubmit();">
    <c:forEach var="name" items="${request.form.availableNames}">
        <c:choose>
            <c:when test="${name[0] == request.form.selectedName}">
                <option value="${name[0]}" selected>
            </c:when>
            <c:otherwise>
                <option value="${name[0]}">
            </c:otherwise>
        </c:choose>
        <c:catch var="error">
            <tags:label key="${name[1]}" />
        </c:catch>
        </option>
    </c:forEach>
</tags:select>

<%-- request.form.styles is an array --%>
<tags:select property="style" collections="${request.form.styles}" valueProperty="0" labelProperty="1" tabindex="4" blank="false" style="width:178px" />


     Coming up next, more on custom HTML Tag and use of HTMLTagTemplate in AJAX.

No comments: