Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
489 views
in Technique[技术] by (71.8m points)

java - Populating one select menu based on another select menu using AJAX in Struts2

I'm trying to use AJAX at very first time in Struts2. Therefore, I do not have precise idea about it.

There are two <s:select>s, one holds a list of countries which is loaded on page load and another holds a list of states that corresponds to the country selected from the country menu.

Therefore, the state menu should be initialized on the onchange JavaScript event triggered by the country menu.

The incomplete version of such a JavaScript function is as follows.

var timeout;
var request;

function getStates(countryId)
{
    if(!request)
    {
        if(countryId===""||countryId===null||countryId===undefined||isNaN(countryId))
        {
            $('#stateList').html("Write an empty <select>");
            alert("Please select an appropriate option.");
            return;
        }

        request = $.ajax({
            datatype:"json",
            type: "GET",
            contentType: "application/json",
            url: "PopulateStateList.action?countryId="+countryId,
            success: function(response)
            {
                if(typeof response==='object'&&response instanceof Array) //Array or something else.
                {
                    $('#stateList').html(writeResponseSomeWay);
                    $('#temp').remove();
                }
            },
            complete: function()
            {
                timeout = request = null;
            },
            error: function(request, status, error)
            {
                if(status!=="timeout"&&status!=="abort")
                {
                    alert(status+" : "+error);
                }
            }
        });
        timeout = setTimeout(function() {
            if(request)
            {
                request.abort();
                alert("The request has been timed out.");
            }
        }, 300000); //5 minutes
    }
}

<s:select> for country:

<s:select id="country" 
          onchange="getStates(this.value);" 
          name="entity.state.countryId" 
          list="countries" value="entity.state.country.countryId" 
          listKey="countryId" listValue="countryName" 
          headerKey="" headerValue="Select" 
          listTitle="countryName"/>

<s:select> for state:

<s:select id="state" 
          name="entity.stateId" 
          list="stateTables" value="entity.state.stateId" 
          listKey="stateId" listValue="stateName" 
          headerKey="" headerValue="Select" 
          listTitle="stateName"/>

The above JavaScript/jQuery function sends an AJAX request to PopulateStateList.action which is mapped to a method in an action class as follows.

List<StateTable>stateTables=new ArrayList<StateTable>(); //Getter only.

@Action(value = "PopulateStateList",
        results = {
            @Result(name=ActionSupport.SUCCESS, location="City.jsp"),
            @Result(name = ActionSupport.INPUT, location = "City.jsp")},
        interceptorRefs={@InterceptorRef(value="modelParamsPrepareParamsStack", params={"params.acceptParamNames", "countryId", "validation.validateAnnotatedMethodOnly", "true", "validation.excludeMethods", "getStateList"})})
public String getStateList() throws Exception
{
    System.out.println("countryId = "+countryId);
    stateTables=springService.findStatesByCountryId(countryId);
    return ActionSupport.SUCCESS;
}

This method is invoked, when a country is selected in its menu and the countryId supplied as a query-string parameter is retrieved but how to return/map this list, stateTables to initialize/populate <s:select> of state menu?


I have earlier used JSON with Jackson and Gson in Spring MVC. Using Gson, for example, a JSON response could simply be mapped like as follows (using a Servlet for the sake of simplicity).

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "AjaxMapServlet", urlPatterns = {"/AjaxMapServlet"})
public class AjaxMapServlet extends HttpServlet
{
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        Map<String, String>map=new HashMap<String, String>();
        map.put("1", "India");
        map.put("2", "America");
        map.put("3", "England");
        map.put("4", "Japan");
        map.put("5", "Germany");

        Type type=new TypeToken<Map<String, String>>(){}.getType();
        Gson gson=new Gson();
        String jsonString=gson.toJson(map, type);
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(jsonString);
    }
}

and in JSP, this Map could be written as follows.

$('#btnMap').click(function() {
    $.get('/TestMVC/AjaxMapServlet', function(responseJson) {
            var $select = $('#mapSelect');
            $select.find('option').remove();
            $('<option>').val("-1").text("Select").appendTo($select)
            $.each(responseJson, function(key, value) {
            $('<option>').val(key).text(value).appendTo($select);
    });
    });
})

<input type="button" id="btnMap" name="btnMap" value="Map"/><br/>
<select id="mapSelect" name="mapSelect"><option>Select</option></select>

<select> will be populated on pressing the given button, btnMap.

What about Struts2? How to populate an <s:select> based on another <s:select>?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The same way you can do it in Struts2, but instead of servlet you can use the action. For example

@Action(value="/PopulateStateList", results=@Result(type="json", params = {"contentType", "application/json", "root", "map"}))
public class AjaxMapAction extends ActionSupport {

  Long countryId; //getter and setter

  Map<String, String> map=new HashMap<String, String>();

  public Map<String, String> getMap() {
    return map;
  }

    @Override
    public String execute() throws Exception {

        map.put("1", "India");
        map.put("2", "America");
        map.put("3", "England");
        map.put("4", "Japan");
        map.put("5", "Germany");

        return SUCCESS;
    }
}

Now, you can use the JSON on the client

  success: function(response)
  {
     if(typeof response==='object') 
     {
        var $select = $('#state');
        $select.find('option').remove();
        $('<option>').val("-1").text("Select").appendTo($select)
        $.each(response, function(key, value) {
        $('<option>').val(key).text(value).appendTo($select);
     }
  },

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...