Ajax实现动态的二级级联菜单
今天花了点时间用Ajax实现了一个二级级联菜单。整理总结一下。为了把重点放在Ajax和级联菜单的实现上,本文省略了数据库建表语句和操作数据库的代码!
数据库建表语句就不帖出来了。主要有两张表,区域表:district。街道表:street。区域表和街道表是一对多关系,一个区域可以有零到多个街道,一条街道属于一个区域。数据如下:

页面代码 index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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=UTF-8">
<script type="text/javascript" src="js/js.js"></script>
<title>Insert title here</title>
</head>
<body>
<select id="district" onchange="cascade(this.value)" >
<option value="-1">请选择</option>
<c:forEach items="${districts }" var="district">
<option value="${district.id }">${district.name }</option>
</c:forEach>
</select>
<select id="street" onchange="alert(this.value)">
<option>请选择</option>
</select>
</body>
</html>
初始化主页面一级菜单列表的Servlet代码 InitServlet.java:
package cascade.servlet;
import java.io.IOException;
import java.util.List; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import cascade.entity.District;
import cascade.service.DistrictService; public class InitServlet extends HttpServlet{ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
} protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
/*
* DistrictService ds为操作数据库的对象.
* 调用该对象的getAllDistrict()方法,可以从数据库中取得所有的区域信息,封装为List<District>对象,并返回。
* 其中District是数据库District表的实体类
* 为了把重点放在Ajax和级联菜单的实现上,本文省略了操作数据库的代码!!!
*/
DistrictService ds = new DistrictService();
List<District> districts = ds.getAllDistrict();
//List<District>对象存在request范围中,并转向到主页
req.setAttribute("districts", districts);
req.getRequestDispatcher("index.jsp").forward(req, resp);
} }
web配置文件 web.xml:
在web.xml中添加如配置代码
<servlet>
<servlet-name>init</servlet-name>
<servlet-class>cascade.servlet.InitServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>init</servlet-name>
<url-pattern>/index</url-pattern>
</servlet-mapping>
此时,在浏览器中访问 InitServlet.java (假设项目名为AjaxCascade,访问地址就是:http://localhost:8080/AjaxCascade/index)
数据库的区域数据就已经填到第一级菜单项中了。

此时页面的源代码可以看到下拉菜单(select)里每一项(option)的value也是从数据库里取到的:
<select id="district" onchange="cascade(this.value)" >
<option value="-1">请选择</option>
<option value="1001">天河区</option>
<option value="1002">越秀区</option>
<option value="1003">海珠区</option>
<option value="1005">番禺区</option>
<option value="1000">白云区</option>
<option value="1004">花都区</option>
</select>
现在开始现实街道下拉菜单(也就是页面上id为street的select)的动态获取。
我们知道,但区域菜单的值改变时,街道菜单的值也要动态的发生改变(如区域选择“天河区”,街道菜单就应该动态加上“中山大道“这一项,如区域选择“海珠区”,街道菜单就应该动态加上“昌岗路”,并删除“中山大道“)。
为了现实上面所说的功能,要为区域菜单添加 onchange 事件的处理:onchange="cascade(this.value)" 当区域菜单值发生改变时调用cascade方法,并把自己的value属性传递进去。
cascade代码如下 js.js:
//XMLHttpRequest组件
var xhs;
//区域菜单的值发生改变时调用该方法,并把区域菜单当前的value传递进来
function cascade(id){
//当id不大于0时,说明当前选择的是“请选择”这一项,则不做操作
if(id>0){
//请求字符串,把区域的id作为页面参数传到后台
var url="cascade?id="+id;
//创建XMLHttpRequest组件
xhs=new XMLHttpRequest();
//设置回调函数,processReuqest方法的定义在下面
xhs.onreadystatechange=processReuqest;
//打开与服务器的地址连接
xhs.open("post", url, true);
//发送请求
xhs.send(null);
}
} //processReuqest方法作为回调方法
function processReuqest(){
if(xhs.readyState==4){
if(xhs.status==200){
//创建新的select节点
var newSelect=document.createElement("select");
newSelect.id="street";
//为新创建的select节点添加onchange事件,以便测试用
newSelect.onchange=function test(){
alert(this.value);
};
//为新创建的select节点添加option节点
var op=document.createElement("option");
op.value=-1;
op.innerHTML="请选择";
newSelect.appendChild(op);
//得到完成请求后返回的字串符
var str = xhs.responseText;
//根据返回的字符串为新创建的select节点添加option节点
var arr1=str.split(",");
for(var i=0;i<arr1.length;i++){
var arr2=arr1[i].split("=");
var child=document.createElement("option");
child.innerHTML=arr2[1];
child.value=arr2[0];
newSelect.appendChild(child);
}
//用新select节点替换旧的select节点
var select = document.getElementById("street");
document.body.replaceChild(newSelect, select);
}
}
}
XMLHttpRequest 对象:XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,包括做出 POST 和 HEAD 请求以及普通的 GET 请求的能力。XMLHttpRequest 可以同步或异步地返回 Web 服务器的响应,并且能够以文本或者一个 DOM 文档的形式返回内容。尽管名为 XMLHttpRequest,它并不限于和 XML 文档一起使用:它可以接收任何形式的文本文档。XMLHttpRequest 对象是名为 AJAX 的 Web 应用程序架构的一项关键功能。
创建XMLHttpRequest 对象:尽管大部份浏览器都支持 new XMLHttpRequest() 来得到 XMLHttpRequest 对象,但IE浏览器和其他Web浏览器返回的 XMLHttpRequest 对象实例是不相同的,为了支持更多浏览器,建议编码时如下所示的代码创建XMLHttpRequest 实例。
function createXmlHttpRequest(){
if(window.ActiveXObject){
return new ActiveXObject("Microsoft.XMLHTTP");
}else if(window.XMLHttpRequest){
return new XMLHttpRequest();
}
}
open(method,url,async)方法:建立于服务器的连接,method参数指定请求的HTTP方法。URL 参数指定请求的地址。acync 参数指定是否使用异步请求,其值为 true 或 false。
send(content)方法:发送请求,content参数指定请求的参数。当send方法不配置参数,即xhr.send()时,在IE中能够正常运行,但在Firefox中却不能,所以,建议最好加上null 。
onreadystatechange属性:指定XMLHttpRequest对象的回调函数。onreadystatechange属性作用与文本框的onblur等属性一样,是事件处理属性,即当 XMLHttpRequest 的状态发生改变时,XMLHttpRequest 对象都会解发onreadystatechange所指定的函数。
readyState属性:XMLHttpRequest的状态信息。XMLHttpRequest对象有如下几种状态。
0:XMLHttpRequest对象没有完成初始化,此时,已经创建一个XMLHttpRequest对象,但是还没有初始化。
1:XMLHttpRequest对象开始发送请求,此时,代码已经调用open()方法并且XMLHttpRequest已经准备好把一个请求发送到服务器。
2:XMLHttpRequest对象的请求发送完成。此时,已经通过send()方法把一个请求发到服务器端,但是还没有收到一个响应。
3:XMLHttpRequest对象开始读取响应。此时,已经接收到HTTP响应头部信息,但是消息体部分还没有完全接收结束。
4:XMLHttpRequest对象读取响应结束。些时,响应已被完全接收。
status属性:HTTP的状态码,仅当readyState的值为3或4时,status属性才可用。status属性如下。
200:服务器响应正常。
400:无法找到请求的资源。
403:没有访问权限。
404:访问资源不存在。
500:服务器内部错误。
responseText属性:获得响应的文本。当readyState值为0、1、2时,reponseText包含一下空字符串。当readyState值为3时,响应中包含还未完成的响应信息。当readyState值为4时,readyState包含完整的响应信息。
接下来是后台代码的实现,从cascade方法可以看到,XMLHttpRequest对象是请求到名为cascade的地址上的。
CascadeServlet.java:
package cascade.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import cascade.entity.District;
import cascade.entity.Street;
import cascade.service.StreetService; public class CascadeServlet extends HttpServlet{ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
} protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
int id =Integer.parseInt(req.getParameter("id"));
District district=new District();
district.setId(id); /*
* StreetService ss为操作数据库的对象.
* 调用该对象的getAllStreet()方法,可以从数据库中取得所有的区域信息,封装为List<Street>对象,并返回。
* 其中Street是数据库Street表的实体类
* 为了把重点放在Ajax和级联菜单的实现上,本文省略了操作数据库的代码!!!
*/
StreetService ss=new StreetService();
List<Street> streets=ss.getAllStreet(district);
//把得到的街道对象集合拼接成字符串文本
StringBuffer sb=new StringBuffer();
for(int i=0;i<streets.size();i++){
sb.append(streets.get(i).getId()).append("=").append(streets.get(i).getName());
if(i!=streets.size()-1){
sb.append(",");
}
}
//servlet不转向或重定向到任何页面,使用resp.getWriter().print()方法可以把文本响应给XMLHttpRequest对象
PrintWriter out = resp.getWriter();
out.print(sb.toString());
out.flush();
out.close();
} }
在web.xml中的配置:
<servlet>
<servlet-name>cascade</servlet-name>
<servlet-class>cascade.servlet.CascadeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cascade</servlet-name>
<url-pattern>/cascade</url-pattern>
</servlet-mapping>
完工,效果如下:



Ajax实现动态的二级级联菜单的更多相关文章
- php 二级级联菜单
找了很多个级联的菜单,都不好用,自己弄个简单点的,共享下,希望有朋友用得着 <?php //建立表country,有三个字段Id,parentId,area. $pro = $_POST['pr ...
- JS动态级联菜单
JS动态级联菜单是前端常用的一个功能,特此抽时间研究了下,附上代码 <html> <head> <meta charset="utf-8" /> ...
- 使用AJAX(阿贾克斯)创建级联菜单
1. html页面 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...
- javascript实现select菜单/级联菜单(用Rails.ajax实现发送请求,接收响应)
在购物网站,填写收货地址的时候,会出现XX省XX市XX区的下拉菜单,如何实现此功能?思路是什么? 功能设置: 当选择省select菜单后,市的select菜单为这个省的城市列. 当选择市菜单后,区菜单 ...
- JS实战 · 级联菜单选择省份和城市(两种)
DOM编程步骤.思路 1.定义界面: 通过html标签将数据进行封装: 2.定义一些静态样式: 利用css: 3.需要动态地完成的和用户的交互: a:明确事件源: ...
- C#动态加载树菜单
在做权限系统的时候,需要有一个树形的菜单.下图就是一个树形菜单的样式 但问题是,我们可以实现写死的树形菜单.什么是写死的?就是在前台代码中写好要加载的树形菜单是什么样子的.但是我们权限系统的要求是动态 ...
- 前台JS(Jquery)调用后台方法 无刷新级联菜单示例
前台用AJAX直接调用后台方法,老有人发帖提问,没事做个示例 下面是做的一个前台用JQUERY,AJAX调用后台方法做的无刷新级联菜单 http://www.dtan.so CasMenu.aspx页 ...
- Excel操作之级联菜单
设置级联菜单主要用的是excel的数据验证功能.下面以简单的设置城市选择框为例: 1.准备好数据 2.给所有省份起个名称(例如:省份),然后同样方法给每个省份所对应的城市以其省份命名,(例如:南京.苏 ...
- js进阶 9-12 js如何实现级联菜单 (章节测试)
js进阶 9-12 js如何实现级联菜单 (章节测试) 一.总结 一句话总结: 1.js如何实现级联菜单 ? 二维数组,以第一级菜单的文本值做键,以对应的二级菜单选项的文本做值 2.用哪个属性可以获 ...
随机推荐
- apache的keepalive和keepalivetimeout
在APACHE的httpd.conf中,KeepAlive指的是保持连接活跃,类似于Mysql的永久连接.换一句话说,如果将KeepAlive设置为On,那么来自同一客户端的请求就不需要再一次连接,避 ...
- .net web api 一
web api可以提供方便简单可靠的web服务,可以大量的用于不需要提供复杂的soap协议的环境,以简单明了的形式返回数据,在不太复杂的环境中web api可以做为wcf等重级web服务的一种可替代方 ...
- Method to fix "Naming information cannot be located because the target principal name is incorrect." for AD replication failure
Assume Failure DC FP01 and Working DC DC01 1. Stop the Key Distribution Center (KDC) service on FP01 ...
- mysql的分页存储过程,能够传出总记录数
最近用mysql + asp.net来写网站,既然mysql已经支持存储过程了,那么像分页这么常用的东西,当然要用存储过程啦 不过在网上找了一些,发现都有一个特点——就是不能传出总记录数,干脆自己研究 ...
- Toast添加动画
WindowManger wm =(WindowManger)context.getSystemService(Context.WINDOW_SERVICE); View view = Toast.m ...
- java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ex.activity/com.ex.activity.LoginActivity}: android.view.InflateException: Binary XML file line #1: Error inflating class
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ex.activity/com.ex.activity.L ...
- php in_array 和 str_replace
有这样的用法哦 $allow_state_array_invoc = array('store_invoice','invoiceno','invoicerec','invoiceing'); if ...
- Python中各种集合 list tuple set dict
list 创建list L = ['Adam','Lucy','Bart'] 索引访问: 正序(和数组类似) L[0],L[1],L[2] 倒序 L[-1]倒数第一个 L[- ...
- Nginx安装配置PHP(FastCGI)环境的教程
这篇是Nginx安装配置PHP(FastCGI)环境的教程.Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用. 一.什么是 FastCGI F ...
- how to remove MouseListener / ActionListener on a JTextField
I have the following code adding an ActionListener to a JTextField: chatInput.addMouseListener(new j ...