Struts 2 Form Control Templates

This, like many other areas of Struts 2 has remained virtually unchanged after it’s port from Webwork. The idea is that you can template the look of your controls in a fine-grained or application-wide level. Suppose you have a fetish for good practice and want to precede every occurrence of an input tag with a label tag like so:

<label for="firstName">First Name</label>
   <input type="text" name="firstName"
          id="firstName"/>

Although you can write a label tag for every input tag manually to achieve this effect, you can also specify a template to render your <s:textfield> tags to reduce the actual code you write in your JSP or Freemarker page.

Create a template called text.ftl in the folder template/mySimpleTheme and make sure template is in your classpath. Include the following in text.ftl:

<label
<#if parameters.id?exists>
for="${parameters.id?html}" <#t/>
</#if>
>${parameters.label?html}</label>

<#include "/${parameters.templateDir}/simple/text.ftl" />

The include file is pointing to a bare-bones template packaged with Struts which renders a simple <input type=”text”/> with all its attributes. All we’re doing in the additional code is doing a check for the existence of an id being passed in via the textfield tag and printing it in a label tag along with the value of label that is being passed in. Now that we’ve got a template to work with, all that’s left to do is use it. Here’s a way you can apply it to a single textfield:

<s:textfield id="firstName" name="firstName"
                theme="mySimpleTheme"
                label="First Name"/>

The above would render:

<label for="firstName">First Name</label>
   <input type="text" name="firstName"
          id="firstName"/>

The theme=”mySimpleTheme” declaration is telling Struts to look for a template in the mySimpleTheme directory under template (the default template directory). If you want this template to render all textfield elements instead of you specifying theme=”mySimpleTheme” every time, you can modify the struts.ui.theme and struts.ui.templateDir properties in struts.properties which have the default values of xhtml and template, respectively. To take a peek at the built-in templates that Struts provides, you’ll need to dig open struts2-core-2.0.6.jar and look at the template folder. This is probably a good exercise for anybody trying to develop a custom UI using Struts 2.

As mentioned the default theme is xhtml which renders <td>’s, <tr>’s and every thing else that is undesirable in markup. If you want to disable the rendering of anything but the attributes of the tag, you can use the provided “simple” theme as such:

<s:textfield id="firstName" name="firstName"
                theme="simple"
                label="First Name"/>

Alternately you could just set the struts.ui.theme to simple in struts.properties. You can also set the template attribute of each control to point to a different templates directory.

The overall mechanism for controlling appearance is completely different than Struts 1.x and somewhat more complex than it might need to be for many cases. It’s probably abstracted by erring on the side of caution and allowing you the freedom to tweak your templates any which way. Some might argue that there is an extremely tight binding between the display of controls and their functionality (both being controlled by Struts tags) and they would be true.

This is a fairly low-level method of controlling the look of a control and CSS is your best bet when trying to render them properly. Struts does use CSS classes when rendering their built-in themes of xhtml and xhtml_css although the naming might not be to your liking. For example, if you use their xhtml_css theme and use <s:textfield>, you’ll end up having to write CSS classes called wwgrp and wwlbl to control the display of labels and input elements.

One quick note, the xhtml_css theme also generates a very worthless <br/> tag between a label and the control which can throw of your entire look, do get rid of this you’ll have to do a .wwgrp br { display: none; } in your CSS stylesheeet.

Advertisements

12 thoughts on “Struts 2 Form Control Templates

  1. Derek

    I wasn’t able to get .wwgrp br { display: none; } to work in Firefox 2.0 with the css_xhtml theme. How did you get this to work, which browser did you use?

    I’m subscribing ot the comments to this post, so I can get your answer.

    Reply
  2. arsenalist

    Try this CSS. It uses “div.wwgrp br” instead of “.wwgrp br” but that shouldn’t make a difference. Maybe it’s one of the other styles that you’re missing.

    This is working fine for me in FF1,2 and IE6,7

    div.wwgrp br {
    display: none;
    }

    div.wwlbl {
    float: left;
    clear: both;
    }

    div.wwctrl {
    float: right;
    }

    Reply
  3. Derek

    Thanks for the info. That worked, but it still isn’t up to the quality of the xhtml theme…. I wish it were because I am a fan of css-based layouts, but in this case I may have to leave the form and the form only rendering with the xhtml template

    Reply
  4. Edson

    Hello, what happing?

    10:57:43,234 ERROR [FreemarkerTemplateEngine] Could not load template /template/mytheme/text
    10:57:43,234 ERROR [UIBean] error when rendering
    freemarker.core.ParseException: Unexpected end of file reached.

    at freemarker.core.FMParser.generateParseException(FMParser.java:4635)
    at freemarker.core.FMParser.jj_consume_token(FMParser.java:4506)
    at freemarker.core.FMParser.LooseDirectiveEnd(FMParser.java:2302)
    at freemarker.core.FMParser.Include(FMParser.java:1699)
    at freemarker.core.FMParser.FreemarkerDirective(FMParser.java:2344)
    at freemarker.core.FMParser.Content(FMParser.java:2574)
    at freemarker.core.FMParser.OptionalBlock(FMParser.java:2742)
    at freemarker.core.FMParser.Root(FMParser.java:2914)
    at freemarker.template.Template.(Template.java:149)
    at freemarker.cache.TemplateCache.loadTemplate(TemplateCache.java:376)
    at freemarker.cache.TemplateCache.getTemplate(TemplateCache.java:347)
    at freemarker.cache.TemplateCache.getTemplate(TemplateCache.java:229)

    Thank you.

    Reply
  5. Edson

    how a could i use select with this example? Has anyone worked with this?
    I try:
    text.ftl :

    for=”${parameters.id?html}”

    >${parameters.label?html}

    jsp:

    but display no values in the list.

    thank you.

    Reply
  6. Edson

    how a could i use select with this example? Has anyone worked with this?
    I try:
    text.ftl :


    for=”${parameters.id?html}”

    >${parameters.label?html}

    jsp:

    but display no values in the list.

    thank you.

    Reply
  7. ebi

    you’ve just help me resolve an issue i had which was basically to remove the row elements from a textfield tag.

    Reply
  8. Seb L.

    Hi,

    It is a very interesting article !

    I would like to know if it is possible to add custom parameter to a template with the <s:param /> tag ? And so, how to get the value of this parameter in the template ?

    Thanks,

    Reply
  9. tenchimyo

    I believe if you specify the labelposition attribute to “left” then this will not produce an extra . By default the label position is on top and that seems to produce this

    Reply
  10. Abby

    Helpful but I think I am still falling short of what I need. I tried understanding the style definitions but still cannot find the default style settings for textfield which is what I am looking for.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s