历史解决方法
1、 在父select元素的onChange事件中增加方法,调用action去填充子select元素。
2、 方法1 的改进,将两个或多个连动select元素放到一个iframe中。
3、 将父select元素和子select元素的内容,在页面初始化时装载到js的变量中,由父select元素的onChange事件直接调用js实现。
4、 方法3 的变形,将父select元素和子select元素的内容,写成独立的js。
历史方法缺点
方法 | 缺点 |
方法1 | 页面得全部刷新,须记住其他已填的内容 |
方法2 | 页面复杂,iframe得全部刷新 |
方法3 | 对于用户的每一次界面操作都得全部加载数据,资源浪费,代码繁多 |
方法4 | 数据库的字典表和js同步有很大问题,更新麻烦 |
我们的目的
1、 页面无需全部刷新;
2、 与字典表更新同步;
3、 减少网络传输资源损耗;
使用方法
准备工作
1、 从http://ajaxtags.sourceforge.net/上下载AjaxTags的最新版本,有源码、demo和doc。
2、 按照demo所示,拷贝资源文件:css、js和lib,还要注意WEB-INF 目录下的ajaxtags.tld。
开始使用
1、 在web.xml文件中加入
<taglib> <taglib-uri>/WEB-INF/ajaxtags.tld</taglib-uri> <taglib-location>/WEB-INF/ajaxtags.tld</taglib-location> </taglib> |
2、 如果你的连动会多处使用,就写成一个.inc文件,使用时就引进来:<%@ include file="/inc/fathertoson.inc"%>
<%@ page contentType="text/html;charset=GBK"%>
<!--ajax的标签库--> <%@ taglib uri="/WEB-INF/ajaxtags.tld" prefix="ajax"%> <!--ajax的css--> <link href="css/ajaxtags.css" rel="stylesheet" type="text/css" /> <link href="css/displaytag.css" rel="stylesheet" type="text/css" /> <!--ajax的js--> <script src="js/prototype-1.3.1.js"></script> <script src="js/ajaxtags-1.1.5.js"></script>
<tr> <td>父select</td> <td> <!—struts的标签--> <html:select property="father" value=""> <html:option value=""> </html:option> <html:options collection="fatherCollection" property="id" labelProperty="name" /> </html:select> </td>
<td>子select</td> <td> <select name="son"> <option selected> </option> </select> </td> </tr>
<!--父子连动--> <ajax:select baseUrl="fatherToSon.do" source="father" target="son" parameters="fathername={father}" />
|
解释一下:
baseUrl 调用action的url;
source 父select
target 子select
parameters="fathername={father}" fathername为action中获得父select值的参数
3、 Action的写法
public class FatherToSonAction extends BaseAjaxAction {
public String getXmlContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 从界面获得父select的值,注意该处使用的是"fathername"而不是"father" String selectValue = request.getParameter("fathername");
// 从数据库中得到子select的列表 ArrayList list = (ArrayList) ...;
// 子select的列表中的对象为子字典对象,具有"name", "id"属性 return new AjaxXmlBuilder().addItems(list, "name", "id").toString(); }
} |
其中BaseAjaxAction和AjaxXmlBuilder可以参照ajax源码进行修改,修改后代码如下:
//================================ AjaxXmlBuilder====================== import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List;
import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang.builder.ToStringBuilder;
/** * Helper class to build valid XML typically returned in a response to the client. * * 生成xml类型文件的帮助类,我们可以将xml文件放到response中返回给客户端 * * @author Darren Spurgeon * @version $Revision$ $Date$ */ public class AjaxXmlBuilder {
private String encoding = "UTF-8";
private List items = new ArrayList();
public String getEncoding() { return encoding; }
public void setEncoding(String encoding) { this.encoding = encoding; }
/** * Add item to XML. * * @param name * The name of the item * @param value * The value of the item * @return */ public AjaxXmlBuilder addItem(String name, String value) { items.add(new Item(name, value, false)); return this; }
/** * Add item wrapped with inside a CDATA element. * * @param name * The name of the item * @param value * The value of the item * @return */ public AjaxXmlBuilder addItemAsCData(String name, String value) { items.add(new Item(name, value, true)); return this; }
/** * Add items from a collection. * * @param collection * @param nameProperty * @param valueProperty * @return * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException */ public AjaxXmlBuilder addItems(Collection collection, String nameProperty, String valueProperty) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { return addItems(collection, nameProperty, valueProperty, false); }
/** * Add items from a collection. * * @param collection * @param nameProperty * @param valueProperty * @return * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException */ public AjaxXmlBuilder addItems(Collection collection, String nameProperty, String valueProperty, boolean asCData) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { for (Iterator iter = collection.iterator(); iter.hasNext();) { Object element = (Object) iter.next(); String name = BeanUtils.getProperty(element, nameProperty); String value = BeanUtils.getProperty(element, valueProperty); if (asCData) { items.add(new Item(name, value, false)); } else { items.add(new Item(name, value, true));
} } return this; }
/** * Add items from a collection as CDATA element. * * @param collection * @param nameProperty * @param valueProperty * @return * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException */ public AjaxXmlBuilder addItemsAsCData(Collection collection, String nameProperty, String valueProperty) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { return addItems(collection, nameProperty, valueProperty, true); }
/** * @see java.lang.Object#toString() */ public String toString() { StringBuffer xml = new StringBuffer().append("<?xml version=/"1.0/""); if (encoding != null) { xml.append(" encoding=/""); xml.append(encoding); xml.append("/""); } xml.append(" ?>");
xml.append("<ajax-response>"); xml.append("<response>"); for (Iterator iter = items.iterator(); iter.hasNext();) { Item item = (Item) iter.next(); xml.append("<item>"); xml.append("<name>"); if (item.isAsCData()) { xml.append("<![CDATA["); } xml.append(item.getName()); if (item.isAsCData()) { xml.append("]]>"); } xml.append("</name>"); xml.append("<value>"); if (item.isAsCData()) { xml.append("<![CDATA["); } xml.append(item.getValue()); if (item.isAsCData()) { xml.append("]]>"); } xml.append("</value>"); xml.append("</item>"); } xml.append("</response>"); xml.append("</ajax-response>");
return xml.toString();
}
}
/** * A generic item class, basically representing a name-value pair. * * 一个通用的item类,代表了一个name-value对 * * @author Darren Spurgoen * @version $Revision$ $Date$ */ class Item {
private String name;
private String value;
private boolean asData;
/** * Constructor for Item. */ public Item() { super(); }
/** * Constructor for Item. * * @param name * @param value */ public Item(String name, String value, boolean asData) { super(); this.name = name; this.value = value; this.asData = asData; }
/** * @return Returns the name. */ public String getName() { return this.name; }
/** * @param name * The name to set. */ public void setName(String name) { this.name = name; }
/** * @return Returns the value. */ public String getValue() { return this.value; }
/** * @param value * The value to set. */ public void setValue(String value) { this.value = value; }
/** * @return Returns the asCData. */ public boolean isAsCData() { return this.asData; }
/** * @param asData * The asData to set. */ public void setAsData(boolean asData) { this.asData = asData; }
/** * @see java.lang.Object#toString() */ public String toString() { return new ToStringBuilder(this).append("name", name).append("value", value).append("asData", asData).toString(); } } |
//========================== BaseAjaxAction==============================
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping;
/** * Ajax应用的祖先抽象类,将xml文件类型数据放到响应流中 * * @author luzhilin * */ public abstract class BaseAjaxAction extends Action {
/** * @see Action#execute(ActionMapping, ActionForm, HttpServletRequest, * HttpServletResponse) */ public final ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
String xml = null; try { xml = getXmlContent(mapping, form, request, response); } catch (Exception ex) { // Send back a 500 error code. response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Can not create response"); return null; }
// Set content to xml response.setContentType("text/xml; charset=UTF-8"); response.setHeader("Cache-Control", "no-cache"); PrintWriter pw = response.getWriter(); pw.write(xml); pw.close();
return null; }
/** * Each child class should override this method to generate the specific XML * content necessary for each AJAX action. * * 每一个子类都必须重写此方法,用于生成特定的xml文件数据流 * * @param mapping * @param form * @param request * the {@javax.servlet.http.HttpServletRequest} object * @param response * the {@javax.servlet.http.HttpServletResponse} object * @return a {@java.lang.String} representation of the XML response/content * @throws Exception */ public abstract String getXmlContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception;
} |
进一步思考的问题
1、 多层连动怎么实现;
2、 多组连动,我们的 action 怎么实现;
posted on 2006-03-08 21:12 野草 阅读(869) 评论(3) 编辑 收藏 所属分类: ajax
<script type="text/javascript"> // </script>评论
# re: 在Struts中使用AjaxTags解决连动问题 2006-10-24 18:30 cdy
为什么我按你说的做了一点反应都没有阿?
今天搞了一天,请指点一点,就是在选中一个select后第二个没有反应
我把我的代码发给你看一下 回复 更多评论
# re: 在Struts中使用AjaxTags解决连动问题 2006-10-24 18:31 cdy
这个是页面代码
<%@ include file="taglibs.jsp"%>
<html>
<head>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/prototype-1.4.0.js"></script>
<script type="text/javascript" src="js/scriptaculous.js"></script>
<script type="text/javascript" src="js/overlibmws.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/ajaxtags-1.2-beta2.js"></script>
<link rel="stylesheet" type="text/css" href="css/ajaxtags.css" />
<link rel="stylesheet" type="text/css" href="css/displaytag.css" />
</head>
<body>
<c:set var="contextPath" scope="request">${pageContext.request.contextPath}</c:set>
<html:form action="/drop" >
question : <html:text property="question" />
<html:errors property="question" />
<br />
firstCatalog : <html:select property="firstCatalogId">
<html:option value="">select firstCatalog</html:option>
<html:options collection="firstCatalogList"
property="firstcatalogid" labelProperty="catalogname" />
</html:select>
<html:errors property="firstCatalog" />
secondCatalog : <select name="secondCatalogId"
disabled="disabled">
<option value="">select secondCatalog</option>
</select>
<html:submit />
<html:cancel />
</html:form>
<ajax:select baseUrl="/drop.do"
source="firstCatalogId"
target="secondCatalogId"
parameters="fId={firstCatalogId}"
/>
</body>
</html>
回复 更多评论
# re: 在Struts中使用AjaxTags解决连动问题 2006-10-24 18:33 cdy
package com.compass;import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.ajaxtags.helpers.AjaxXmlBuilder;
import org.ajaxtags.servlets.BaseAjaxAction;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import com.Dao.CatalogDao;
public class DropAction extends BaseAjaxAction {
public String getXmlContent(
ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response)
throws Exception {
String firstCatalogId = request.getParameter("fId");
CatalogDao catalogDao = new CatalogDao();
List list = catalogDao.getSecondCatalogList(firstCatalogId);
//获得子select
return new AjaxXmlBuilder().addItems(list, "secondcatalogid", "catalogname").toString();
}
}