Struts2 UI tags are used to generate HTML form elements in result pages. Earlier we looked into Struts2 Data Tags and Struts2 Control tags and how we can use OGNL expressions with Struts2 tags. This tutorial is aimed to provide details about the most commonly used Struts2 UI tags with a simple project.
Struts 2 UI Tags
Struts 2 UI tags provides following functionalities out of the box:
- Generating HTML markup language
- Binding HTML form data to Action classes properties
- Tie into Struts2 framework type conversion from String to Objects and vice versa
- Tie into Struts2 framework Validation and i18n support
Struts 2 UI Tags Examples
Some of the important Struts2 UI tags are:
- form tag: We can create HTML form with form tag, this tag not only generates the HTML markup but also generates form id, method and action with servlet context URI. For example if we use Struts2 form tag as below
<s:form action="Welcome" namespace="/"> </s:form>
The corresponding HTML getting generated is:
<form id="Welcome" name="Welcome" action="/Struts2UITags/Welcome.action" method="post"> <table class="wwFormTable"> </table></form>
Notice that in action, it automatically includes the web application servlet context and action prefix for Struts2 invocation. It also creates a table with specific class that we can use for having our own CSS styling.
- textfield tag: One of the most widely used Struts2 UI tags to create input element for user input in form. When we use this tag, it generates a table row with two columns, one for the label and another for the user input with type as text. For example;
<s:textfield name="name" label="User Name"></s:textfield>
Generated html is:
<tr> <td class="tdLabel"><label for="Welcome_name" class="label">User Name:</label></td> <td ><input type="text" name="name" value="" id="Welcome_name"/></td> </tr>
- password tag:Same as textfield tag except that fields are not shown and input type is password.
<s:password name="password" label="Password"></s:password>
generated html snippet is
<tr> <td class="tdLabel"><label for="Welcome_password" class="label">Password:</label></td> <td ><input type="password" name="password" id="Welcome_password"/></td> </tr>
- textarea tag: Used to create textarea html element in the form. We can specify the textarea size with cols and rows attribute.
<s:textarea name="bio" label="About You" cols="20" rows="3" wrap="true"></s:textarea>
generated html code is
<tr> <td class="tdLabel"><label for="Welcome_bio" class="label">About You:</label></td> <td ><textarea name="bio" cols="20" rows="3" wrap="true" id="Welcome_bio"></textarea></td> </tr>
- checkbox tag: Used to generate checkbox element in the html form.
<s:checkbox name="receiveUpdates" fieldValue="true" label="Check to receive updates."></s:checkbox>
generated html code is
<tr> <td valign="top" align="right"> </td> <td valign="top" align="left"> <input type="checkbox" name="receiveUpdates" value="true" id="Welcome_receiveUpdates"/><input type="hidden" id="__checkbox_Welcome_receiveUpdates" name="__checkbox_receiveUpdates" value="true" /> <label for="Welcome_receiveUpdates" class="checkboxLabel">Check to receive updates.</label> </td> </tr>
- select tag: Used to generate select box in the html page. We can use multiple attribute to allow multiple selections.
<s:select list="{'Developer','Manager','Customer'}" name="rolesSelect" multiple="true"></s:select>
generated html code is
<tr> <td class="tdLabel"></td> <td ><select name="rolesSelect" id="Welcome_rolesSelect" multiple="multiple"> <option value="Developer">Developer</option> <option value="Manager">Manager</option> <option value="Customer">Customer</option> </select> <input type="hidden" id="__multiselect_Welcome_rolesSelect" name="__multiselect_rolesSelect" value="" /> </td> </tr>
- checkboxlist tag: Similar to select box, only difference is in the rendering of the checkboxes.
<s:checkboxlist list="{'Developer','Manager','Customer'}" name="roleCheckbox"></s:checkboxlist>
generated html snippet is
<tr> <td class="tdLabel"></td> <td > <input type="checkbox" name="roleCheckbox" value="Developer" id="roleCheckbox-1" /> <label for="roleCheckbox-1" class="checkboxLabel">Developer</label> <input type="checkbox" name="roleCheckbox" value="Manager" id="roleCheckbox-2" /> <label for="roleCheckbox-2" class="checkboxLabel">Manager</label> <input type="checkbox" name="roleCheckbox" value="Customer" id="roleCheckbox-3" /> <label for="roleCheckbox-3" class="checkboxLabel">Customer</label> <input type="hidden" id="__multiselect_Welcome_roleCheckbox" name="__multiselect_roleCheckbox" value="" /> </td> </tr>
- radio tag: We can use this tag to generate radio buttons in the html page.
<s:radio list="{'Developer','Manager','Customer'}" name="rolesRadio" multiple="true"></s:radio>
generated html is
<tr> <td class="tdLabel"></td> <td > <input type="radio" name="rolesRadio" id="Welcome_rolesRadioDeveloper" value="Developer" multiple="true"/><label for="Welcome_rolesRadioDeveloper">Developer</label> <input type="radio" name="rolesRadio" id="Welcome_rolesRadioManager" value="Manager" multiple="true"/><label for="Welcome_rolesRadioManager">Manager</label> <input type="radio" name="rolesRadio" id="Welcome_rolesRadioCustomer" value="Customer" multiple="true"/><label for="Welcome_rolesRadioCustomer">Customer</label> </td> </tr>
- doubleselect tag: We can use this tag to link together two select boxes so that changing the value in first box changes the choices in the second select box. For example
<s:doubleselect list="{'Developer','Manager','Tester'}" name="doubleSelectRole" label="Role" doubleList="top == 'Developer' ? {'Java','PHP'} : (top == 'Manager' ? {'HR Manager', 'Finance Manager'} : {'UI Testing', 'Functional Testing'})" doubleName="doubleSelectExpertise"></s:doubleselect>
Generated html code is
<tr> <td class="tdLabel"><label for="Welcome_doubleSelectRole" class="label">Role:</label></td> <td > <select name="doubleSelectRole" id="Welcome_doubleSelectRole" onchange="Welcome_doubleSelectRoleRedirect(this.selectedIndex)"> <option value="Developer">Developer</option> <option value="Manager">Manager</option> <option value="Tester">Tester</option> </select> <br> <select name="doubleSelectExpertise" id="Welcome_doubleSelectExpertise" > </select> <script type="text/javascript"> var Welcome_doubleSelectRoleGroup = new Array(3 + 0); for (i = 0; i < (3 + 0); i++) Welcome_doubleSelectRoleGroup[i] = new Array(); Welcome_doubleSelectRoleGroup[0][0] = new Option("Java", "Java"); Welcome_doubleSelectRoleGroup[0][1] = new Option("PHP", "PHP"); Welcome_doubleSelectRoleGroup[1][0] = new Option("HR Manager", "HR Manager"); Welcome_doubleSelectRoleGroup[1][1] = new Option("Finance Manager", "Finance Manager"); Welcome_doubleSelectRoleGroup[2][0] = new Option("UI Testing", "UI Testing"); Welcome_doubleSelectRoleGroup[2][1] = new Option("Functional Testing", "Functional Testing"); var Welcome_doubleSelectRoleTemp = document.Welcome.Welcome_doubleSelectExpertise; Welcome_doubleSelectRoleRedirect(0); function Welcome_doubleSelectRoleRedirect(x) { var selected = false; for (m = Welcome_doubleSelectRoleTemp.options.length - 1; m >= 0; m--) { Welcome_doubleSelectRoleTemp.remove(m); } for (i = 0; i < Welcome_doubleSelectRoleGroup[x].length; i++) { Welcome_doubleSelectRoleTemp.options[i] = new Option(Welcome_doubleSelectRoleGroup[x][i].text, Welcome_doubleSelectRoleGroup[x][i].value); } if ((Welcome_doubleSelectRoleTemp.options.length > 0) && (! selected)) { Welcome_doubleSelectRoleTemp.options[0].selected = true; } } </script> </td> </tr>
Notice that it automatically creates the javascript code that otherwise we would have to write on our own.
- submit tag: Used to create submit button in the html page to submit the form.
<s:submit value="Submit"></s:submit>
generated html code is
<tr> <td colspan="2"><div align="right"><input type="submit" id="Welcome_0" value="Submit"/> </div></td> </tr>
Let’s create a simple Struts2 project where we can see the UI tags usage. Our final project will look like below image.
Configuration Files
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Struts2UITags</display-name> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
Deployment descriptor has configuration to use Struts2 framework.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Struts2UITags</groupId> <artifactId>Struts2UITags</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.3.15.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <warSourceDirectory>WebContent</warSourceDirectory> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> <finalName>${project.artifactId}</finalName> </build> </project>
Maven project configuration with struts2-core dependency.
struts.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.convention.result.path" value="/"></constant> <package name="user" namespace="/" extends="struts-default"> <action name="home"> <result>/home.jsp</result> </action> <action name="Welcome" class="com.journaldev.struts2.actions.WelcomeAction"> <result name="success">/welcome.jsp</result> </action> </package> </struts>
Simple package and action mapping with result pages.
Java Bean
package com.journaldev.struts2.actions; public class User { private String name; private String password; private String bio; private boolean receiveUpdates; private String[] rolesSelect; private String roleCheckbox; private String[] rolesRadio; private String doubleSelectRole; private String doubleSelectExpertise; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getBio() { return bio; } public void setBio(String bio) { this.bio = bio; } public boolean isReceiveUpdates() { return receiveUpdates; } public void setReceiveUpdates(boolean receiveUpdates) { this.receiveUpdates = receiveUpdates; } public String[] getRolesSelect() { return rolesSelect; } public void setRolesSelect(String[] rolesSelect) { this.rolesSelect = rolesSelect; } public String getRoleCheckbox() { return roleCheckbox; } public void setRoleCheckbox(String roleCheckbox) { this.roleCheckbox = roleCheckbox; } public String[] getRolesRadio() { return rolesRadio; } public void setRolesRadio(String[] rolesRadio) { this.rolesRadio = rolesRadio; } public String getDoubleSelectExpertise() { return doubleSelectExpertise; } public void setDoubleSelectExpertise(String doubleSelectExpertise) { this.doubleSelectExpertise = doubleSelectExpertise; } public String getDoubleSelectRole() { return doubleSelectRole; } public void setDoubleSelectRole(String doubleSelectRole) { this.doubleSelectRole = doubleSelectRole; } }
A simple java bean with getter and setter methods for properties. Some of the variables are array where we are expecting multiple values in the form.
Action Class
package com.journaldev.struts2.actions; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; public class WelcomeAction extends ActionSupport implements ModelDriven<User> { @Override public String execute(){ return SUCCESS; } private User user = new User(); @Override public User getModel() { return user; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
Simple action class that is basically forwarding the request to another result page to generate the response.
Result Pages
home.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Home Page</title> </head> <body> <s:form action="Welcome" namespace="/"> <s:textfield name="name" label="User Name"></s:textfield> <s:password name="password" label="Password"></s:password> <s:textarea name="bio" label="About You" cols="20" rows="3" wrap="true"></s:textarea> <s:checkbox name="receiveUpdates" fieldValue="true" label="Check to receive updates."></s:checkbox> <s:select list="{'Developer','Manager','Customer'}" name="rolesSelect" multiple="true"></s:select> <s:checkboxlist list="{'Developer','Manager','Customer'}" name="roleCheckbox"></s:checkboxlist> <s:radio list="{'Developer','Manager','Customer'}" name="rolesRadio" multiple="true"></s:radio> <s:doubleselect list="{'Developer','Manager','Tester'}" name="doubleSelectRole" label="Role" doubleList="top == 'Developer' ? {'Java','PHP'} : (top == 'Manager' ? {'HR Manager', 'Finance Manager'} : {'UI Testing', 'Functional Testing'})" doubleName="doubleSelectExpertise"></s:doubleselect> <s:submit value="Submit"></s:submit> </s:form> </body> </html>
This is the result page where Struts2 UI tags are getting used to generate HTML response page for client. User can fill in the details and submit the form to action class.
When home action is invoked, the generated HTML page looks like below image.
The generated HTML response by the result page code is:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Home Page</title> </head> <body> <form id="Welcome" name="Welcome" action="/Struts2UITags/Welcome.action" method="post"> <table class="wwFormTable"> <tr> <td class="tdLabel"><label for="Welcome_name" class="label">User Name:</label></td> <td ><input type="text" name="name" value="" id="Welcome_name"/></td> </tr> <tr> <td class="tdLabel"><label for="Welcome_password" class="label">Password:</label></td> <td ><input type="password" name="password" id="Welcome_password"/></td> </tr> <tr> <td class="tdLabel"><label for="Welcome_bio" class="label">About You:</label></td> <td ><textarea name="bio" cols="20" rows="3" wrap="true" id="Welcome_bio"></textarea></td> </tr> <tr> <td valign="top" align="right"> </td> <td valign="top" align="left"> <input type="checkbox" name="receiveUpdates" value="true" id="Welcome_receiveUpdates"/><input type="hidden" id="__checkbox_Welcome_receiveUpdates" name="__checkbox_receiveUpdates" value="true" /> <label for="Welcome_receiveUpdates" class="checkboxLabel">Check to receive updates.</label> </td> </tr> <tr> <td class="tdLabel"></td> <td ><select name="rolesSelect" id="Welcome_rolesSelect" multiple="multiple"> <option value="Developer">Developer</option> <option value="Manager">Manager</option> <option value="Customer">Customer</option> </select> <input type="hidden" id="__multiselect_Welcome_rolesSelect" name="__multiselect_rolesSelect" value="" /> </td> </tr> <tr> <td class="tdLabel"></td> <td > <input type="checkbox" name="roleCheckbox" value="Developer" id="roleCheckbox-1" /> <label for="roleCheckbox-1" class="checkboxLabel">Developer</label> <input type="checkbox" name="roleCheckbox" value="Manager" id="roleCheckbox-2" /> <label for="roleCheckbox-2" class="checkboxLabel">Manager</label> <input type="checkbox" name="roleCheckbox" value="Customer" id="roleCheckbox-3" /> <label for="roleCheckbox-3" class="checkboxLabel">Customer</label> <input type="hidden" id="__multiselect_Welcome_roleCheckbox" name="__multiselect_roleCheckbox" value="" /> </td> </tr> <tr> <td class="tdLabel"></td> <td > <input type="radio" name="rolesRadio" id="Welcome_rolesRadioDeveloper" value="Developer" multiple="true"/><label for="Welcome_rolesRadioDeveloper">Developer</label> <input type="radio" name="rolesRadio" id="Welcome_rolesRadioManager" value="Manager" multiple="true"/><label for="Welcome_rolesRadioManager">Manager</label> <input type="radio" name="rolesRadio" id="Welcome_rolesRadioCustomer" value="Customer" multiple="true"/><label for="Welcome_rolesRadioCustomer">Customer</label> </td> </tr> <tr> <td class="tdLabel"><label for="Welcome_doubleSelectRole" class="label">Role:</label></td> <td > <select name="doubleSelectRole" id="Welcome_doubleSelectRole" onchange="Welcome_doubleSelectRoleRedirect(this.selectedIndex)"> <option value="Developer">Developer</option> <option value="Manager">Manager</option> <option value="Tester">Tester</option> </select> <br> <select name="doubleSelectExpertise" id="Welcome_doubleSelectExpertise" > </select> <script type="text/javascript"> var Welcome_doubleSelectRoleGroup = new Array(3 + 0); for (i = 0; i < (3 + 0); i++) Welcome_doubleSelectRoleGroup[i] = new Array(); Welcome_doubleSelectRoleGroup[0][0] = new Option("Java", "Java"); Welcome_doubleSelectRoleGroup[0][1] = new Option("PHP", "PHP"); Welcome_doubleSelectRoleGroup[1][0] = new Option("HR Manager", "HR Manager"); Welcome_doubleSelectRoleGroup[1][1] = new Option("Finance Manager", "Finance Manager"); Welcome_doubleSelectRoleGroup[2][0] = new Option("UI Testing", "UI Testing"); Welcome_doubleSelectRoleGroup[2][1] = new Option("Functional Testing", "Functional Testing"); var Welcome_doubleSelectRoleTemp = document.Welcome.Welcome_doubleSelectExpertise; Welcome_doubleSelectRoleRedirect(0); function Welcome_doubleSelectRoleRedirect(x) { var selected = false; for (m = Welcome_doubleSelectRoleTemp.options.length - 1; m >= 0; m--) { Welcome_doubleSelectRoleTemp.remove(m); } for (i = 0; i < Welcome_doubleSelectRoleGroup[x].length; i++) { Welcome_doubleSelectRoleTemp.options[i] = new Option(Welcome_doubleSelectRoleGroup[x][i].text, Welcome_doubleSelectRoleGroup[x][i].value); } if ((Welcome_doubleSelectRoleTemp.options.length > 0) && (! selected)) { Welcome_doubleSelectRoleTemp.options[0].selected = true; } } </script> </td> </tr> <tr> <td colspan="2"><div align="right"><input type="submit" id="Welcome_0" value="Submit"/> </div></td> </tr> </table></form> </body> </html>
welcome.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Welcome Page</title> </head> <body> <h3>User Details</h3> User Name: <s:property value="name"></s:property><br> <s:hidden name="password"></s:hidden> About You: <s:property value="bio"></s:property><br> Receiving Updates: <s:property value="receiveUpdates"></s:property><br> Roles Selected: <s:property value="rolesSelect"/><br> Role Checkbox Value: <s:property value="roleCheckbox"/><br> Roles Radio Value: <s:property value="rolesRadio"/><br><br> Double Select Role: <s:property value="doubleSelectRole"/><br> Double Select Expertise: <s:property value="doubleSelectExpertise"/><br> <h4>Thank You</h4> </body> </html>
A simple JSP page that is showing the values entered by the used in the form. The response html page looks like below image.
Did you noticed the hidden tag, we can use this tag to generate hidden element in the html page. The name attribute corresponds to the java bean property of the action class.
That’s all for Struts2 UI tags example project, you can download the project from below link and play around with different attributes available for different UI tags.