One request I've seen on the displaytag-user list a few times is the ability to change a <tr>'s CSS class based on a certain value. While the displaytag doesn't have this feature out-of-the-box, it is possible (and fairly easy) to do. All you need to do is sprinkle a little JavaScript into the mix. Basically, the displaytag will render a well-formed HTML table - like the following:
Username |
First Name |
Last Name |
mraible |
Matt |
Raible |
tomcat |
Tomcat |
User |
By adding an "id" attribute to your table (i.e. id="user"), your table will get an "id" attribute and now you can easily access it via the DOM. The following JavaScript will grab the table and search the first column for a value of 'mraible' - and if found, it will change the row's background color to red.
<script type="text/javascript">
<!--
var table = document.getElementById("user");
var tbody = table.getElementsByTagName("tbody")[0];
var rows = tbody.getElementsByTagName("tr");
// add event handlers so rows light up and are clickable
for (i=0; i < rows.length; i++) {
var value = rows[i].getElementsByTagName("td")[0].firstChild.nodeValue;
if (value == 'mraible') {
rows[i].style.backgroundColor = "red";
}
}
//-->
</script>
You could easily change rows[i].style... to rows[i].className = if you want to assign a new CSS class. Now let's see it in action (and see if your browser supports it). This has only been tested in Safari and Mozilla on OS X.
Username |
First Name |
Last Name |
mraible |
Matt |
Raible |
tomcat |
Tomcat |
User |
Other displaytag tips: Static Headers HowTo and Highlight and allow clicking of rows. The 2nd tip (highlighting) is available in AppFuse, in the userList.jsp page.
BTW, I also added support for the DisplayTag to render the results from JSTL's SQL Tag. I haven't committed it yet - I'm still waiting for more feedback.
A frequent issue that crops up when using Struts is how to transfer data from ActionForms to DTOs or POJOs and vise-versa. In other words, how do you get the data from your true model into Struts' Model? There are a few solutions out there, including the ActionForm-Value Object Mapper and BeanUtils.copyProperties. I've used both and (IMO) the only advantage of using BeanUtils is that Struts uses it internally and it's a bit easier to work with.
The reason I'm writing this post is to show you how to handle Dates and Doubles in your POJOs. The first step is easy - you simply need to register converters for Date and Doubles. The easiest way to do this (that I know of) is to add a static block to one of your classes. I do this in
BaseManager, but it could be easily done in a BaseForm class.
static {
ConvertUtils.register(new CurrencyConverter(), Double.class);
ConvertUtils.register(new DateConverter(), Date.class);
if (log.isDebugEnabled()) {
log.debug("Converters registered...");
}
}
|
When I use Doubles, it tends to be for dollar amounts displayed in a JSP page. Therefore, I call it a CurrencyConverter (source), and I use a DateConverter (source) for dates.
After registering these converters, the next step is to throw a little validation into the mix so that the String values (from the Form) are in an expected format. Since I'm using XDoclet to generate my Forms, it's as easy as adding a couple of tags to my POJO. Here is an example for validation Dates:
/**
* @return Returns the startDate.
* @struts.validator type="required"
* @struts.validator type="date"
* @struts.validator-var name="datePatternStrict" value="MM/dd/yyyy"
* @hibernate.property column="start_date" not-null="true"
*/
public Date getStartDate() {
return startDate;
}
|
And one for validating dollar amounts:
/**
* @return Returns the startingSalary.
* @struts.validator type="required"
* @struts.validator type="mask" msgkey="errors.currency"
* @struts.validator-var name="mask" value="${currency}"
* @hibernate.property column="salary_start" not-null="true"
*/
public Double getStartingSalary() {
return startingSalary;
}
|
For the currency validation to work, you have to add a few things to your Struts project. The first is the errors.currency to your ApplicationResources.properties file:
errors.currency=The '{0}' field should be a dollar amount.
The 2nd piece you'll need to add is the currency mask as a constant in your validation.xml file (or metadata/web/validation-global.xml if you're using XDoclet/AppFuse):
<constant>
<constant-name>currency</constant-name>
<constant-value>^\d{1,3}(,?\d{1,3})*\.?(\d{1,2})?$</constant-value>
</constant>
I'm not much of a regular expression expert, but I think this mask is specific to US Dollar amounts. I'd love to see a i18n version, but I haven't had a need for one (yet) - so it's not a big deal for me. The last thing you'll need to do is add a little JSTL lovin' to render your dollar amounts with the proper number of decimal places:
<fmt:formatNumber type="number" minFractionDigits="0"
maxFractionDigits="2" value="${myForm.startingSalary}"/>
It seems that most web frameworks are getting away from a separate web model (ActionForms) and allowing you to use your POJOs in your view. This is likely to be a bit cleaner, but I'm sure they still have to use some sort of converter to get Dates/Doubles from your UI into your POJOs. The nice thing I've seen in other frameworks is that they have Date Converters built in. Why doesn't Struts? Who knows, but IMO it should be a built-in component.
Both of the Converters described in this article can be found in AppFuse.