5.2 submit 和 a 标签
a 和 submit 这 2 个标签的作用几乎完全一样,除了外在的表现不一样 ( a 标签生成一个超链接、submit 标签生成一个提交按钮) 。它们都是用于向服务器发送异步请求,并将服务器响应加载在指定的 HTML 元素中。使用这 2 个标签时可以指定如下几个常用属性:
● href : 指定单击这 2 个标签生成的超链接、按钮时发送请求的 URL
● targets : 指定一个或多个 HTML 元素的 ID,该属性值指定的多个 HTML 元素将作为服务器响应的容器,用于自动显示服务器响应
● executeScripts : 设置是否指定远端的 JavaScript 代码
● handler : 指定使用本页面的 JavaScript 函数作为按钮、超链接点击事件处理函数(如果指定了该属性,则不会想远程服务器发送 Ajax 请求,即使指定了 href 属性也没用)
除此之外, 这 2 个标签也支持使用 pub-sub 的事件模型,即可以为这 2 个标签指定如下属性:
● notifyTopics : 指定系列事件主题名,多个主题之间用 (,) 隔开。配置该属性的 HTML 元素将会把 load 事件(成功装载了服务器响应之后) 发布到指定主题,发布主题时会专递 3 个参数: data 、 type 、 request
当然,为了提供更友好的用户界面,Struts 2 也可设置交互过程中的提示信息,这些提示信息包括指定如下2 个属性
● loadingText : 指定当服务器响应还未成功装载时、targets 属性指定的 HTML 元素中显示的提示信息
● errorText : 指定与服务器的交互之间存在错误时,targets 属性指定的 HTML 元素中显示的提示信息
2 个标签都可用于将表单的请求参数通过异步方式发送到服务器,为了指定发送哪个表单里包含的请求参数,可以为这 2 个标签指定如下 2 个属性
● formId : 设置将 form 属性指定的表单里包含的表单域转换成请求参数,并以异步方式发送到服务器
● formFilter : 指定一个函数用于过滤指定表单内的表单域
例子:
/dojo/sx-a.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>远程链接</title>
<sx:head/>
<script type="text/javascript">
function before() {alert("before request");}
function after() {alert("after request");}
function handler(widget, node)
{
alert('本地JavaScript处理函数');
dojo.byId(widget.targetsArray[0]).innerHTML
= "疯狂Java讲义";
}
dojo.event.topic.subscribe("/after"
, function(data, type, e)
{
alert('正处于Dojo的异步交互过程中,类型是:' + type);
});
</script>
</head>
<body >
<div id="t1" style="background-color:#bbbbbb;width:360px;height:80px">div 1</div><br/>
<div id="t2" style="background-color:#bbbbbb;width:360px;height:80px">div 2</div><br/>
同时修改div1和div2的内容<br/>
且将事件发布到/after主题(指定notifyTopics属性)<br/>
<sx:a id="link1" href="ajaxTest.action" indicator="indicator"
targets="t1,t2" notifyTopics="/after" >修改div1和div2内容</sx:a>
<img id="indicator" src="images/indicator.gif" alt="Loading..." style="display:none"/>
<br/><br/>
指定服务期返回失败时的错误提示(指定errorText属性)<br/>
因为系统中AjaxNoUrl.jsp页面不存在,肯定出错!<br/>
<sx:a id="link2" href="/dojo/AjaxNoUrl.jsp" errorText="系统服务器返回信息出错"
targets="t1">修改'div 1'的内容,使用自定义出错提示</sx:a>
<br/><br/>
指定系统加载中的提示信息(指定loadingText属性)<br/>
<sx:a id="link3" href="ajaxTest.action" loadingText="系统正在加载中..."
targets="t1">修改'div 1'的内容,使用自定义Loading信息</sx:a>
<br/><br/>
执行远程JavaScript代码(指定executeScripts=true属性)<br/>
<sx:a id="link4" href="test.action" executeScripts="true"
targets="t2">接执行远程JavaScript,更新'div 2'的内容</sx:a>
<br/><br/>
通过使用本地JavaScript函数来实现Ajax交互(指定handler属性)<br/>
<sx:a id="link5" href="ajaxTest.action" handler="handler" targets="t2">使用本地JavaScript处理函数</sx:a>
<br/><br/>
<form id="form">
<input type="textbox" name="data" />
</form>
提交表单请求(通过指定formId属性)<br />
<sx:a id="link6" href="ajaxTest.action" targets="t2"
formId="form">div 2 会显示在上面文本框中输入的内容</sx:a>
</body>
</html>
上面页面中生成了一系列超链接。因为第 1 个超链接 的 targets 属性指定了 div1 和 div2 作为装载服务器响应的容器。因此,当单击第一个超链接时,看到前面两个 div 元素的内容被更新
对于第 2 个 超链接 ,其 href 属性指向的 URL 并不存在,因此单击该超链接时肯定出现错误,而且为生成超链接的 <sx:a> 标签指定了 errorText 属性,因此,当单击该超链接时,可以看到第一个 div 元素显示自定义的错误提示
对于第 3 个 超链接 ,指定了该标签的 loadingText 属性,该属性设置未成功装载服务器响应时,该 div 元素显示的提示信息。因此,当单击该链接时,可以在该 div 元素中看到 “系统正在加载中。。。” 的短暂显示
第 4 个 超链接 ,则可以执行远程服务器响应的 JavaScript 函数 ( 通过指定 executeScripts='true' 属性 )
第 5 个 超链接 ,则直接触发本地 JavaScript 函数 ( 指定了 handler='handler' 属性 )
第 6 个 超链接 ,则会发送上面表单里包含的表单域请求参数,如果在上面文本框中输入字符,然后点击第 6 个超链接,则可在第 2 个 div 中看到输入内容。因为上面的异步请求发送一个请求参数,所以 Action 中也应该包含一个对应的属性,该属性用于封装请求参数。
提示 : 处理 Ajax 请求的 Action 类,与处理普通请求的 Action 没有任何区别,配置也没有任何区别。区别是 Action 的结果页面,处理 Ajax 请求的结果页,无需使用完整的 HTML 标签,而只需输出必须更新的数据;而对于普通请求的结果页,则需要使用完整的 HTML 页面
/dojo/sx-submit.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>远程按钮</title>
<sx:head/>
<script type="text/javascript">
dojo.event.topic.subscribe("/after"
, function(data, type, e)
{
alert('正处于Dojo的异步交互过程中,类型是:' + type);
});
</script>
</head>
<body>
<div id="t1" style="background-color:#bbbbbb;width:360px;height:80px">盛装服务器响应的div元素</div>
简单的提交按钮,使用indicator<br/>
<img id="indicator" alt="Loading..." style="display:none"
src="${pageContext.request.contextPath}/images/indicator.gif" />
<!-- targets属性设置用于装载服务器响应的HTML元素 -->
<sx:submit type="submit" value="提交" targets="t1" href="ajaxTest.action" indicator="indicator"/>
<br/><br/>
简单的提交按钮,使用pub-sub事件模型(设置notifyTopics=/after属性)<br />
<sx:submit type="submit" value="提交" targets="t1" href="ajaxTest.action" notifyTopics="/after"/>
<br/><br/>
图片按钮(通过指定type="image")<br />
<sx:submit type="image" label="测试Label" targets="t1" src="images/struts-power.gif" href="ajaxTest.action"/>
<br/><br/>
异步方式提交表单:(在下面输入的文本将在上面显示出来)
<s:form id="form" action="ajaxTest">
<input type="text" name="data"/>
<sx:submit type="button" label="发送" targets="t1" />
</s:form>
</body>
</html>
第 1 个按钮 ,只是一个简单的 Ajax 按钮,当单击按钮时,看到服务器响应会被加载在上面的灰色 div 元素中。
第 2 个按钮 ,因为使用了 pub-sub 事件模型,将该元素的 Ajax 交互中各过程中的事件都发布到 /after 事件主题下,而该事件主题下注册了一个简单的订阅者。
第 3 个按钮 ,只是设置其 type 属性为 image,可以将该按钮设置成一个图片按钮,该图片按钮与普通的行为没有任何区别,只是外在表现有所不同
第 4 个按钮 ,用于异步方式提交表单参数。div 中可以看到文本框输入的内容
实际上,使用 <sx:submit> 生成按钮来异步提交表单有 2 种方式:
● 为<sx:submit>指定 formId 属性,该属性的值是需要提交的表单的 ID,这种方式与前面的通过超链接来提交表单的做法完全一样
● 将 <sx:submit> 标签作为 <s:form > 标签的子标签,这正是上面示例代码中的用法。也是前面介绍异步表单时所使用的方式
通过 Struts 2 的 Ajax 表单的支持,我们可以采用异步方式提交表单请求。与传统的提交表单请求相比,提交 Ajax 表单的请求参数后,当前页面不会提交,浏览者依然可以在当前页面继续自己的动作,直到服务器响应到达时,Struts 2 会自动加载服务器响应。
struts.xml
<?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.2.dtd"> <struts> <constant name="struts.custom.i18n.resources" value="messageResource"/> <constant name="struts.i18n.encoding" value="UTF-8"/> <package name="js.dojo" extends="struts-default"> <action name="random" class="js.dojo.RandomAction"> <result>/dojo/randomStr.jsp</result> </action> <!-- 配置ajaxText Action --> <action name="ajaxTest" class="js.dojo.AjaxTestAction"> <result>/dojo/ajaxResult.jsp</result> </action> <action name="test"> <result>/dojo/testjs.jsp</result> </action> <action name="books"> <result>/dojo/data_zh_CN</result> </action> <action name="getBooks" class="js.dojo.GetBooksAction"> <result>/dojo/books.jsp</result> </action> <action name="showPerson" class="js.dojo.ShowPersonAction"> <result>/dojo/showPerson.jsp</result> </action> <action name="getChild" class="js.dojo.GetChildNode"> <result>/dojo/bookNode.jsp</result> </action> <action name=""> <result>.</result> </action> </package> </struts>
AjaxTestAction
package js.dojo;
import com.opensymphony.xwork2.ActionSupport;
public class AjaxTestAction extends ActionSupport {
private static int counter = 0;
// 封装请求参数的属性
private String data;
public long getServerTime() {
return System.currentTimeMillis();
}
public int getCount() {
return ++counter;
}
// data属性的setter和getter方法
public void setData(String data) {
// 将Dojo的请求参数转换成正常字符
this.data = HTMLDecoder.decode(data);
}
public String getData() {
return "服务器提示:" + this.data;
}
}
/dojo/ajaxResult.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
request.setAttribute("decorator", "none");
//阻止浏览器缓存
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0);
%>
服务器计数器: <s:property value="count"/><br/>
当前时间是:<s:property value="serverTime"/><br/>
服务器返回的提示是:<s:property value="data"/>
<s:a href="" οnclick="newWin('dojo/sx-a.jsp');" cssStyle="cursor: hand;">sx-a.jsp</s:a>
<s:a href="" οnclick="newWin('dojo/sx-submit.jsp');" cssStyle="cursor: hand;">sx-sumbit.jsp</s:a>
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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 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>struts2</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <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>
HTMLDecoder
package js.dojo;
public class HTMLDecoder {
public static String decode(String str) {
// 获取字符串中所有数字
String[] tmp = str.split(";&#|&#|;");
StringBuffer sb = new StringBuffer("");
// 处理每个tmp数组中每个字符串元素
for (int i = 0; i < tmp.length; i++) {
// 如果该元素是5位数字,将其转换成非西欧字符
if (tmp[i].matches("\\d{5}")) {
sb.append((char) Integer.parseInt(tmp[i]));
}
// 对于普通字符
else {
sb.append(tmp[i]);
}
}
return sb.toString();
}
}
5.3 autocompleter 标签
以下代码都基于 5.2
autocompleter 标签会生成一个带下拉按钮的单行文本输入框,当用户单击下拉按钮时,将看到一系列的选项,单击某个选项时可以将选项填入单行文本框。
下拉选择框的选项会在页面加载时自动加载,而且随着用户在单行文本框中输入时改变: 当用户输入字符串时,下拉列表框的选项总是单行文本框中内容以某种方式匹配 。此时,用户可以通过上、下箭头来选择合适的选项,并将选项填入单行文本框。
如果设置 autocompleter 标签的 autoComplete 属性为 true (默认 false ) ,该标签将会在单行文本框中生成输入提示。如果希望强制用户只能输入下拉列表中的列表项,则可以设置 forceValidOption 属性为 true (默认 false ) 。
每个 autocompleter 标签都会生成 2 个 HTML 的 input 元素,一个 input 元素是一个单行文本框,另一个是隐藏域。如果指定 autocompleter 标签的 name 属性是 abc ,则生成的单行文本框的 name 为 abc ,而隐藏的 name 为 abcKey 。 abc 单行文本框里的 value 则是 autocompleter 标签生成的单行输入框中字符串,而 abcKey 隐藏域的 value 则是该标签的 value
提示: 当在表单中使用 autocompleter 标签时,一个 autocompleter 标签即对应 2 个输入参数。其中第一个输入参数是单行文本框,另一个输入参数是隐藏域
使用该标签时可以指定如下几个常用属性:
● autoComplete : 设置是否在单行文本输入框中显示提示输入
● forceValidOption : 设置单行文本框内是否只接受下拉列表框里的列表项
● delay : 指定显示下拉列表框之前的延迟时间
● href : 指定异步生成下拉列表项的 URL
● searchType : 设置下拉列表项与单行文本框的字符串的匹配模式,可以接受 3 个值: startstring ( 显示以文本框中字符串开头的选项,这是默认值)、startword ( 显示以文本框中单词开头的选项) 、substring ( 显示包含文本框中字符串的选项)
● dropdownHeight : 设置下拉列表框的高度,默认是 120
● dropdownWidth : 设置下拉列表框的宽度,默认与单行文本框的宽度相同。
● formId : 指定将哪个表单里的表单域转换为请求参数作为异步请求的参数
● value : 指定 input 元素的默认值
● list : 指定用于迭代生成下拉选项的集合
● loadOnTextChange : 设置当用户在单行文本框内输入时,是否重新加载列表项
● loadMinimumCount : 当 loadOnTextChange 属性设置为 true 时,该属性设置输入多少字符后,才会触发重新加载列表项
● showDownArrow : 是否显示下拉箭头,默认是显示
因为 autocompleter 标签要求服务器响应可以被解析成下拉框表项,而 autocompleter 是使用 JSON 格式来解析服务器响应的,所以要求服务器响应格式如下:
[ ["display Text1","value1"], ["display Text2","value2"] ]
上面的服务器响应将被解析成 2 个选项,第一个选项 的显示文本是 display Text1 ,对应值为 value1 ;第二个选项 的显示文本是 display Text2 ,对应值为 value2
服务器响应也可是 JSON 格式的对象,如下:
{ "display Text1":"value1", "display Text2":"value2" }
/struts2/WebContent/dojo/sx-autocompleter1.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>自动完成</title>
<sx:head/>
</head>
<body>
服务器(/books.action)总是返回一个简单的JSON list。<br/>
不使用自动完成(autoComplete="false")。<br/>
使用indicator<br/>
字符串匹配模式是子串匹配(searchType="substring")<br/>
<sx:autocompleter
name="book1" indicator="indicator1" href="books.action"
cssStyle="width:200px;" autoComplete="false" searchType="substring"/>
<img id="indicator1" src="images/indicator.gif" alt="Loading..." style="display:none"/>
<br/>
<br/>
用户输入时重新加载下拉列表项(loadOnTextChange="true")<br/>
当3个字符后才触发重新加载下拉列表(loadMinimumCout="3")<br/>
不出现下拉箭头 (showDownArrow="false")<br/>
<sx:autocompleter
name="book2" indicator="indicator" href="books.action"
cssStyle="width: 200px;" autoComplete="false" loadOnTextChange="true"
loadMinimumCount="3" showDownArrow="false"/>
<img id="indicator" src="images/indicator.gif" alt="Loading..." style="display:none"/>
<br/>
<br/>
设置在文本框中提示自动完成(autoComplete="true")。<br/>
<sx:autocompleter
name="book3" href="books.action" cssStyle="width: 200px;" autoComplete="true" />
<br/>
<br/>
使用本页面的集合来自动完成<br/>
<sx:autocompleter
list="{'疯狂Java讲义','轻量级Java EE企业实战','疯狂Ajax讲义'}" cssStyle="width: 240px;"/>
<br/>
<br/>
校验用户输入,强制只能输入下拉列表项(forceValidOption="true")<br/>
<sx:autocompleter
name="book4" href="books.action" forceValidOption="true" cssStyle="width: 200px;"/>
<br/>
<br/>
设置dropdown的高度是180px (dropdownHeight="180")<br/>
<sx:autocompleter
name="book5" href="books.action" dropdownHeight="180" cssStyle="width: 200px;" />
<br/>
<br/>
禁用combobox功能 (disabled="true")<br/>
<sx:autocompleter
name="book6" href="books.action" disabled="true" cssStyle="width: 200px;" />
</body>
</html>
当输入 “疯狂” 之后,系统会自动出现一个下拉列表,列出所有以疯狂开头的选项,且在单行文本框中自动完成。
上面所有 <sx:autocompleter> 标签的 href 都指向 books.action 该 Action 直接映射到一个数据页面,并没有进行任何额外的处理,如下:
/dojo/data_zh_CN
[ ["\u75af\u72c2Java\u8bb2\u4e49"], ["\u8f7b\u91cf\u7ea7Java EE\u4f01\u4e1a\u5b9e\u6218"], ["\u75af\u72c2Ajax\u8bb2\u4e49"], ["\u75af\u72c2XML\u8bb2\u4e49"] ]
相对中文:
[ ["疯狂Java讲义"], ["轻量级Java EE企业实战"], ["疯狂Ajax讲义"], ["疯狂XML讲义"] ]
struts.xml 参照 5.2
index.jsp
<s:a href="" οnclick="newWin('dojo/sx-autocompleter1.jsp');" cssStyle="cursor: hand;">sx-autocompleter1.jsp</s:a>
源代码 html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>自动完成</title> <script language="JavaScript" type="text/javascript"> // Dojo configuration djConfig = { isDebug: false, bindEncoding: "GBK" ,baseRelativePath: "/struts2/struts/dojo/" ,baseScriptUri: "/struts2/struts/dojo/" ,parseWidgets : false }; </script> <script language="JavaScript" type="text/javascript" src="/struts2/struts/dojo/struts_dojo.js"></script> <script language="JavaScript" type="text/javascript" src="/struts2/struts/ajax/dojoRequire.js"></script> <link rel="stylesheet" href="/struts2/struts/xhtml/styles.css" type="text/css"/> <script language="JavaScript" src="/struts2/struts/utils.js" type="text/javascript"></script> <script language="JavaScript" src="/struts2/struts/xhtml/validation.js" type="text/javascript"></script> <script language="JavaScript" src="/struts2/struts/css_xhtml/validation.js" type="text/javascript"></script> </head> <body> 服务器(/books.action)总是返回一个简单的JSON list。<br/> 不使用自动完成(autoComplete="false")。<br/> 使用indicator<br/> 字符串匹配模式是子串匹配(searchType="substring")<br/> <input dojoType="struts:ComboBox" dataUrl="books.action" id="book1" style="width:200px;" searchType="SUBSTRING" autoComplete="false" name="book1" keyName="book1Key" indicator="indicator1" visibleDownArrow="true" /> <script language="JavaScript" type="text/javascript">djConfig.searchIds.push("book1");</script> <img id="indicator1" src="images/indicator.gif" alt="Loading..." style="display:none"/> <br/> <br/> 用户输入时重新加载下拉列表项(loadOnTextChange="true")<br/> 当3个字符后才触发重新加载下拉列表(loadMinimumCout="3")<br/> 不出现下拉箭头 (showDownArrow="false")<br/> <input dojoType="struts:ComboBox" dataUrl="books.action" id="book2" style="width: 200px;" autoComplete="false" name="book2" keyName="book2Key" indicator="indicator" loadOnType="true" loadMinimum="3" visibleDownArrow="false" /> <script language="JavaScript" type="text/javascript">djConfig.searchIds.push("book2");</script> <img id="indicator" src="images/indicator.gif" alt="Loading..." style="display:none"/> <br/> <br/> 设置在文本框中提示自动完成(autoComplete="true")。<br/> <input dojoType="struts:ComboBox" dataUrl="books.action" id="book3" style="width: 200px;" autoComplete="true" name="book3" keyName="book3Key" visibleDownArrow="true" /> <script language="JavaScript" type="text/javascript">djConfig.searchIds.push("book3");</script> <br/> <br/> 使用本页面的集合来自动完成<br/> <select dojoType="struts:ComboBox" style="width: 240px;" keyName="nullKey" visibleDownArrow="true" > <option value="疯狂Java讲义">疯狂Java讲义</option> <option value="轻量级Java EE企业实战">轻量级Java EE企业实战</option> <option value="疯狂Ajax讲义">疯狂Ajax讲义</option> </select> <script language="JavaScript" type="text/javascript">djConfig.searchIds.push("");</script> <br/> <br/> 校验用户输入,强制只能输入下拉列表项(forceValidOption="true")<br/> <input dojoType="struts:ComboBox" dataUrl="books.action" id="book4" style="width: 200px;" forceValidOption="true" name="book4" keyName="book4Key" visibleDownArrow="true" /> <script language="JavaScript" type="text/javascript">djConfig.searchIds.push("book4");</script> <br/> <br/> 设置dropdown的高度是180px (dropdownHeight="180")<br/> <input dojoType="struts:ComboBox" dataUrl="books.action" id="book5" style="width: 200px;" dropdownHeight="180" name="book5" keyName="book5Key" visibleDownArrow="true" /> <script language="JavaScript" type="text/javascript">djConfig.searchIds.push("book5");</script> <br/> <br/> 禁用combobox功能 (disabled="true")<br/> <input dojoType="struts:ComboBox" dataUrl="books.action" id="book6" style="width: 200px;" disabled="disabled" name="book6" keyName="book6Key" visibleDownArrow="true" /> <script language="JavaScript" type="text/javascript">djConfig.searchIds.push("book6");</script> </body> </html>
除此之外,还可以使用 <sx:autocompleter> 进行异步提交表单,异步提交表单有 2 种方式:
● 为 <sx:autocompleter> 标签指定 formId 属性,该属性值指向需要异步提交的表单
● 将 <sx:autocompleter> 标签作为 <s:form> 的子标签使用
下面代码演示了 2 个 <sx:autocompleter> 标签的关联,第二个 <sx:autocompleter> 的选项会随第一个 <sx:autocompleter> 中值选择的改变而改变。 思路: 使用第一个 <sx:autocompleter> 元素来提交请求参数,而第二个 <sx:autocompleter> 的选项根据第一个 <sx:autocompleter> 请求参数来加载选项。
为了让第二个 <sx:autocompleter> 的选项会随第一个 <sx:autocompleter> 的值的改变,需要让第二个 <sx:autocompleter> 的加载选项随第一个 <sx:autocompleter> 的值的改变而重新加载。为了达到这个效果,将第一个<sx:autocompleter> 的事件注册为某个主题发布者,将第二个 <sx:autocompleter> 注册成该事件主题的订阅者。
如下:
/dojo/sx-autocompleter2.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>自动完成</title>
<sx:head/>
</head>
<body>
<h3>将两个sx:autocompleter关联起来</h3>
<form id="selectForm">
请选择您喜欢的作者:<br/>
<sx:autocompleter name="author"
list="{'李刚','Rod Johnson' , 'David Flanagan'}" value="李刚"
notifyTopics="/books" forceValidOption="true"/>
</form>
<br/><br/>
请选择您喜欢的图书:<br/>
<sx:autocompleter name="book" href="getBooks.action"
cssStyle="width: 240px;" autoComplete="false"
formId="selectForm" listenTopics="/books" forceValidOption="true"/>
</body>
</html>
GetBooksAction
package js.dojo;
import java.util.ArrayList;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
public class GetBooksAction extends ActionSupport {
private String author;
private List<String> books = new ArrayList<String>();
// author属性的setter和getter方法
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = HTMLDecoder.decode(author);
}
// books属性的getter方法
public List<String> getBooks() {
return books;
}
// 处理用户请求的execute方法
public String execute() throws Exception {
if (author.equals("李刚")) {
books.clear();
books.add("疯狂Java讲义");
books.add("轻量级Java EE企业应用实战");
books.add("疯狂Ajax讲义");
books.add("疯狂XML讲义");
} else if (author.equals("Rod Johnson")) {
books.clear();
books.add("Expert One-on-One J2EE" + " Design and Development");
} else if (author.equals("David Flanagan")) {
books.clear();
books.add("JavaScript权威指南");
}
return SUCCESS;
}
}
/dojo/books.jsp
<%@ page contentType="text/html;charset=GBK" language="java" pageEncoding="GBK"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
{
<s:iterator value="books">
"<s:property/>":"<s:property/>",
</s:iterator>
}
struts.xml 参照 5.2
index.jsp
<s:a href="" οnclick="newWin('dojo/sx-autocompleter2.jsp');" cssStyle="cursor: hand;">sx-autocompleter2.jsp</s:a>
解释: 下面略微解释其运行过程: 由于第一个 <sx:autocompleter> 标签注册为 /books 主题的发布者,当用户改变该元素里的内容时,将发布一个事件到第二个 <sx:autocompleter>
由于第二个 <sx:autocompleter> 被注册为 /books 主题的订阅者,因此该元素被激发,它将会向服务器发生异步请求,又由于该标签指定了 formId="selectForm" ,因此它会把 selectForm 里的表单域转换为请求参数、以异步方式发送到服务器。值得指出的是: selectForm 里正好包含第一个 <sx:autocompleter> 标签,也就是说,会将第一个 <sx:autocompleter> 内的选项作为参数发送到服务器
源代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>自动完成</title>
<script language="JavaScript" type="text/javascript">
// Dojo configuration
djConfig = {
isDebug: false,
bindEncoding: "GBK"
,baseRelativePath: "/struts2/struts/dojo/"
,baseScriptUri: "/struts2/struts/dojo/"
,parseWidgets : false
};
</script>
<script language="JavaScript" type="text/javascript"
src="/struts2/struts/dojo/struts_dojo.js"></script>
<script language="JavaScript" type="text/javascript"
src="/struts2/struts/ajax/dojoRequire.js"></script>
<link rel="stylesheet" href="/struts2/struts/xhtml/styles.css" type="text/css"/>
<script language="JavaScript" src="/struts2/struts/utils.js" type="text/javascript"></script>
<script language="JavaScript" src="/struts2/struts/xhtml/validation.js" type="text/javascript"></script>
<script language="JavaScript" src="/struts2/struts/css_xhtml/validation.js" type="text/javascript"></script>
</head>
<body>
<h3>将两个sx:autocompleter关联起来</h3>
<form id="selectForm">
请选择您喜欢的作者:<br/>
<select dojoType="struts:ComboBox" id="author" forceValidOption="true" name="author" keyName="authorKey" initialValue="李刚" notifyTopics="/books" visibleDownArrow="true" >
<option value="李刚" selected="selected">李刚</option>
<option value="Rod Johnson">Rod Johnson</option>
<option value="David Flanagan">David Flanagan</option>
</select>
<script language="JavaScript" type="text/javascript">djConfig.searchIds.push("author");</script>
</form>
<br/><br/>
请选择您喜欢的图书:<br/>
<input dojoType="struts:ComboBox" dataUrl="getBooks.action" id="book" style="width: 240px;" forceValidOption="true" autoComplete="false" name="book" keyName="bookKey" formId="selectForm" listenTopics="/books" visibleDownArrow="true" />
<script language="JavaScript" type="text/javascript">djConfig.searchIds.push("book");</script>
</body>
</html>