Struts 2 <s:doubleselect> example

In Struts 2 , the <s:doubleselect> tag is used to create two HTML drop down boxes, once the first drop down list is selected, the second drop down list will be change accordingly. A very classic example is the “country” and “state” drop down selection, where different “state” lists are depending on the selected “country“.

A <s:doubleselect> tag


<s:doubleselect label="Fruits (OGNL) " 
name="fruit1" list="{'fruit','meat'}" 
doubleName="fruit2" 
doubleList="top == 'fruit' ? {'apple', 'orange','banana'} : {'chicken', 'pig'}" />

Resulting the following HTML code…


<tr> 
<td class="tdLabel">
  <label for="resultAction_fruit1" class="label">
     Fruits (OGNL) :
  </label>
</td> 
<td> 
<select name="fruit1" id="resultAction_fruit1" 
    onchange="resultAction_fruit1Redirect(this.options.selectedIndex)"> 
    <option value="fruit">fruit</option> 
    <option value="meat">meat</option> 
</select> 
<br /> 
<select name="fruit2" id="resultAction_fruit2"> 
</select> 
<script type="text/javascript"> 
    var resultAction_fruit1Group = new Array(2 + 0);
    for (i = 0; i < (2 + 0); i++)
    resultAction_fruit1Group[i] = new Array();
 
    resultAction_fruit1Group[0][0] = new Option("apple", "apple");
 
    resultAction_fruit1Group[0][1] = new Option("orange", "orange");
 
    resultAction_fruit1Group[0][2] = new Option("banana", "banana");
 
    resultAction_fruit1Group[1][0] = new Option("chicken", "chicken");
 
    resultAction_fruit1Group[1][1] = new Option("pig", "pig");
 
 
    var resultAction_fruit1Temp = document.resultAction.resultAction_fruit2;
    resultAction_fruit1Redirect(0);
    function resultAction_fruit1Redirect(x) {
    	var selected = false;
        for (m = resultAction_fruit1Temp.options.length - 1; m >= 0; m--) {
            resultAction_fruit1Temp.options[m] = null;
        }
 
        for (i = 0; i < resultAction_fruit1Group[x].length; i++) {
            resultAction_fruit1Temp.options[i] = 
	     new Option(
              resultAction_fruit1Group[x][i].text, resultAction_fruit1Group[x][i].value
             );
         }
 
        if ((resultAction_fruit1Temp.options.length > 0) && (! selected)) {
           	resultAction_fruit1Temp.options[0].selected = true;
        }
    }
</script>   
</td> 
</tr> 

Well, the <s:doubleselect> tag is really generate a lot of codes. It will create two drop down lists, many JavaScript’s codes to do the magic behind (first select, second change), and also attached a “onchange()” behavior to the first drop down box.

Look complicated, but simple!
It’s just two <s:select> tags combine in a single tag, see clearly again.


<s:doubleselect
name="" list="" 
doubleName="" doubleList="" />

The “name” and “list” is refer to the first drop down lists; the “doubleName” and “doubleList” is refer to the second drop down list. The data population is same with the “<s:select>” tag.

Struts 2 <s:doubleselect> example

A complete full example of the <s:doubleselect> tag, show the use of OGNL or Java lists to populate the data to the drop down lists.

1. Action

Action class to generate and hold the two drop down lists.
DoubleSelectAction.java


package com.mkyong.common.action;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.opensymphony.xwork2.ActionSupport;

public class DoubleSelectAction extends ActionSupport{

	private String fruit1;
	private String fruit2;
	
	private String server1;
	private String server2;
	
	private String language1;
	private String language2;
	
	Map languageMap;

	public String getFruit1() {
		return fruit1;
	}

	public void setFruit1(String fruit1) {
		this.fruit1 = fruit1;
	}

	public String getFruit2() {
		return fruit2;
	}

	public void setFruit2(String fruit2) {
		this.fruit2 = fruit2;
	}

	public String getServer1() {
		return server1;
	}

	public void setServer1(String server1) {
		this.server1 = server1;
	}

	public String getServer2() {
		return server2;
	}

	public void setServer2(String server2) {
		this.server2 = server2;
	}

	public String getLanguage1() {
		return language1;
	}

	public void setLanguage1(String language1) {
		this.language1 = language1;
	}

	public String getLanguage2() {
		return language2;
	}

	public void setLanguage2(String language2) {
		this.language2 = language2;
	}

	public Map getLanguageMap() {
		return languageMap;
	}

	public void setLanguageMap(Map languageMap) {
		this.languageMap = languageMap;
	}

	public DoubleSelectAction(){
	  languageMap =new HashMap();		
		
          languageMap.put("Java", 
            new ArrayList<String>(Arrays.asList("Spring", "Hibernate", "Struts 2")));
          languageMap.put(".Net", new ArrayList<String>(Arrays.asList("VB.Net", "C#")));
          languageMap.put("JavaScript", new ArrayList<String>(Arrays.asList("jQuery")));
	}

	public String execute() {
		return SUCCESS;
	}
	
	public String display() {
		return NONE;
	}
	
}

2. Result page

Render two drop down boxes via “<s:doubleselect>” tag, and populate the lists via Java list and OGNL list

doubleselect.jsp


<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
</head>

<body>
<h1>Struts 2 <s:doubleselect> example</h1>

<s:form action="resultAction" namespace="/">

<s:doubleselect label="Fruits (OGNL) " 
name="fruit1" list="{'fruit','meat'}" 
doubleName="fruit2" 
doubleList="top == 'fruit' ? {'apple', 'orange','banana'} : {'chicken', 'pig'}" />

<s:set name="serverList" 
     value="#{
         'AppServer': {'Apache', 'Tomcat', 'JBoss'},
         'Database': {'Oracle', 'MySQL'}
         }" />
<s:doubleselect label="Server (OGNL) " 
name="server1" list="#serverList.keySet()" 
doubleName="server2" doubleList="#serverList[top]" />

<s:doubleselect label="Language (Java List) " 
name="language1" list="languageMap.keySet()" 
doubleName="language2" doubleList="languageMap.get(top)" />

<s:submit value="submit" name="submit" />
	
</s:form>

</body>
</html>

result.jsp


<%@ taglib prefix="s" uri="/struts-tags" %>
<html>

<body>
<h1>Struts 2 <s:doubleselect> example</h1>

<h2>
  Test #1 : <s:property value="fruit1"/> , <s:property value="fruit2"/>
</h2> 

<h2>
  Test #2 : <s:property value="server1"/> , <s:property value="server2"/>
</h2> 

<h2>
  Test #2 : <s:property value="language1"/> , <s:property value="language2"/>
</h2> 

</body>
</html>

3. struts.xml

Link all together ~


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
 
<struts>

 <constant name="struts.devMode" value="true" />
 	
<package name="default" namespace="/" extends="struts-default">
		
   <action name="doubleSelectAction" 
         class="com.mkyong.common.action.DoubleSelectAction" method="display">
	<result name="none">pages/doubleselect.jsp</result>
   </action>
		
   <action name="resultAction" class="com.mkyong.common.action.DoubleSelectAction">
	<result name="success">pages/result.jsp</result>
   </action>
  </package>
	
</struts>

5. Demo

http://localhost:8080/Struts2Example/doubleSelectAction.action

Struts 2 double select example

http://localhost:8080/Struts2Example/resultAction.action

Struts 2 double select example

Reference

  1. Struts 2 double select documentation
  2. Struts 2 <s:select> example
  3. http://chuanliang2007.spaces.live.com/blog/cns!E5B7AB2851A4C9D2!393.entry

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

avatar
12 Comment threads
7 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
13 Comment authors
ParufredAlexMosheAjay Upadhyay Recent comment authors
newest oldest most voted
Alex
Guest
Alex

Hi,

Great work, nice examples. I only have a question. What’s the name of this structure on OGNL?

#{‘AppServer’: {‘Apache’, ‘Tomcat’, ‘JBoss’},
‘Database’: {‘Oracle’, ‘MySQL’}
}

Is it a special kind of map or something?

I’m trying to fill the elements of the list using a property of an Action class using a Map, but cannot get it work.

Moshe
Guest
Moshe

I have this error, have been trying to solve this for 3 days with no results.

org.apache.jasper.JasperException: tag ‘doubleselect’, field ‘list’, name ‘language1?: The requested list key ‘languageMap.keySet()’ could not be resolved as a collection/array/map/enumeration/iterator type. Example: people or people.{name}

Maybe someone have the answer for this please?

Deep
Guest
Deep

I am going nuts…. what could be the possible reason for this below error and how to correct it. In my case the first is able to get the list from Action-Class, but populates blank list on second

==================================
FreeMarker template error!

Expression parameters.formName is undefined on line 111, column 43 in template/simple/doubleselect.ftl.
The problematic instruction:
———-
==> ${parameters.formName} [on line 111, column 41 in template/simple/doubleselect.ftl]
———-

Java backtrace for programmers:
———-
freemarker.core.InvalidReferenceException: Expression parameters.formName is undefined on line 111, column 43 in template/simple/doubleselect.ftl.
at freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:124)
at freemarker.core.Expression.getStringValue(Expression.java:118)
at freemarker.core.Expression.getStringValue(Expression.java:93)
at freemarker.core.DollarVariable.accept(DollarVariable.java:76)
at freemarker.core.Environment.visit(Environment.java:210)
at freemarker.core.MixedContent.accept(MixedContent.java:92)

Ajay Upadhyay
Guest
Ajay Upadhyay

I am facing the same error. I had used only the JSP code. Do you suggest to also create Action and then execute the code.

Max
Guest
Max

I used your source code and obtain this error:

org.apache.jasper.JasperException: tag ‘doubleselect’, field ‘list’, name ‘language1’: The requested list key ‘languageMap.keySet()’ could not be resolved as a collection/array/map/enumeration/iterator type. Example: people or people.{name} – [unknown location]

Can you resolve it?

Thanks in advance

smitha
Guest
smitha

have u resolved this error??? i am getting same

fred
Guest
fred

I had to put around the <s:form…etc

Paru
Guest
Paru

Cud you pls share the solution?Facing the same error!

Moshe
Guest
Moshe

Hey I’m facing this error too, have you resolved this?

Moshe
Guest
Moshe

Hey I’m facing this error too, have you resolved this?

pete
Guest
pete

great job – straight and to-the-point

trackback
Struts 2 Tutorial

[…] upload example.Upload multiple files example Struts 2 <s:file> multiple file upload example.doubleselect example Struts 2 <s:doubleselect>, create two HTML drop down boxes, once the first drop down list is […]

Jerson
Guest
Jerson

Hi,
Thanks alot for this example…..This is it dud

Many Thanks

Tumble Dryers
Guest
Tumble Dryers

~;’ I am very thankful to this topic because it really gives up to date information ;~’

Hui Zhou
Guest
Hui Zhou

I think I have cleared the cache. Because I always run command “mvn clean package”, then run command “mvn jetty:run” to run the web application.

The only modification I make to the source code is to add jetty plugin in pom.xml.

But when I enter into http://localhost:8080/Struts2Example/doubleSelectAction.action, I get those warning messages mentioned above.

Hui Zhou
Guest
Hui Zhou

While running the code, I got some warning as below:

WARNING: Caught an exception while evaluating expression ‘top == ‘fruit’ ? {‘apple’, ‘orange’,’banana’} : {‘chicken’, ‘pig’}’ against value stack
java.lang.IllegalArgumentException: invalid comparison: com.mkyong.common.action.DoubleSelectAction and java.lang.String
at ognl.OgnlOps.compareWithConversion(OgnlOps.java:92)
at ognl.OgnlOps.isEqual(OgnlOps.java:142)
at ognl.OgnlOps.equal(OgnlOps.java:794)
WARNING: Could not find method [languageMap.get(top)]

But the function seems to be working.

trackback
Struts 2 <s:optiontransferselect> example

[…] Struts 2 doubleselect example […]

trackback
Struts 2 updownselect example