示例效果: http://tams.oschina.mopaas.com/demo/ComponentTest 图:
其中,父列表的改变会影响“子列表1”和“子列表2”,而“子列表2”的改变又会影响“孙子列表(与子列表2进行联动)”。横向子列表有2个,纵向子孙列表有2个,很具有代表性,现在看看使用Component组件库的 Combobox组件是如何做到这么复杂的级联的呢。
tml模板代码如下:
<html title="Not found tapestry-demo" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd" xmlns:r="tapestry-library:rjzjh" xmlns:p="tapestry:parameter"> <head> <title isMenu="true" module="3">component组件示例</title> </head> <body> <h1>列表的级联</h1><br/> 父列表: <r:combobox id="parentList" textField="text" valueField="id" url="nolan:/resource/demo/json.txt" panelHeight="100" value="1"/> 子列表1: <r:combobox id="subList" textField="text" valueField="id" parent="parentList" url="/demo/componenttest:querySub" value="12"></r:combobox> 子列表2: <r:combobox id="subList1" textField="text" valueField="id" parent="parentList" url="/demo/componenttest:querySub" value="11"></r:combobox> 孙子列表(与子列表2进行联动) <r:combobox id="subList11" textField="text" valueField="id" parent="subList1" url="/demo/componenttest:querySubSub"></r:combobox> </body> </html>
“父列表”与普通列表没什么两样,URL有一个 url="nolan:/resource/demo/json.txt" 这个是Component组件库的一个地址的封装,代表不用加语言前缀的地址,也就是说在国际化项目中这个地址是不会做任何改变的,不会在前面加上 “/en”、“/zh”之类的。
唯一注意点就是 parent 参数,它设置当前下拉列表的级联父列表的Id,示例 parent="parentList"指的就是当前列表的级联父列表是 “父列表”这个列表。
Java代码如下:
package cn.rjzjh.tapestry.tams.pages.demo; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.apache.tapestry5.util.TextStreamResponse; import cn.rjzjh.commons.util.apiext.JSONUtil; import cn.rjzjh.commons.util.apiext.StringUtil; import cn.rjzjh.tapestry.tams.base.ParentPage; public class ComponentTest extends ParentPage { public static final List<Map<String, String>> jsonList = new ArrayList<Map<String, String>>(); public static final List<Map<String, String>> jsonList2 = new ArrayList<Map<String, String>>(); static { Map<String, String> obj1 = new HashMap<String, String>(); obj1.put("id", "11"); obj1.put("text", "text11"); jsonList.add(obj1); Map<String, String> obj2 = new HashMap<String, String>(); obj2.put("id", "12"); obj2.put("text", "text12"); jsonList.add(obj2); Map<String, String> obj3 = new HashMap<String, String>(); obj3.put("id", "21"); obj3.put("text", "text21"); jsonList.add(obj3); Map<String, String> obj4 = new HashMap<String, String>(); obj4.put("id", "31"); obj4.put("text", "text31"); jsonList.add(obj4); //孙子列表 Map<String, String> obj11 = new HashMap<String, String>(); obj11.put("id", "111"); obj11.put("text", "text111"); jsonList2.add(obj11); Map<String, String> obj12 = new HashMap<String, String>(); obj12.put("id", "112"); obj12.put("text", "text112"); jsonList2.add(obj12); } public TextStreamResponse onQuerySub() { final String parentId = request.getParameter("parent"); if(StringUtil.isNull(parentId)){ return retStream("[]"); } List<Map<String, String>> selList = (List<Map<String, String>>) CollectionUtils .select(jsonList, new Predicate() { @Override public boolean evaluate(Object arg0) { Map<String, String> temp = (Map<String, String>) arg0; return temp.get("id").startsWith(parentId); } }); String ret = JSONUtil.getJsonForListAlias(selList); return retStream(ret); } public TextStreamResponse onQuerySubSub() { final String parentId = request.getParameter("parent"); if(StringUtil.isNull(parentId)){ return retStream("[]"); } List<Map<String, String>> selList = (List<Map<String, String>>) CollectionUtils .select(jsonList2, new Predicate() { @Override public boolean evaluate(Object arg0) { Map<String, String> temp = (Map<String, String>) arg0; return temp.get("id").startsWith(parentId); } }); String ret = JSONUtil.getJsonForListAlias(selList); return retStream(ret); } }
Java类就列简单了,onQuerySub方法就是指这个地址“url="/demo/componenttest:querySub"调用的方法,而onQuerySubSub方法则是指子孙列表Url “url="/demo/componenttest:querySubSub"”调用的方法。
唯 一要注意点就是:final String parentId = request.getParameter("parent"); 这个指在父列表的子有值的改变时会把父的值通过参数“parent”传递到每个子列表中。子列表只要跟据这引值筛选出符合条件的项返回到前台就可以了。是不是很简单。