eXtremeTable本质上是一个form组件,所以我假定表被包在form里,所有的功能都被认为是对form元素的操作。如果你想在表体中包含一些定制的form元素, 或者想将eXtremeTable嵌入到另外的form中,那么你就要使用表标签的form属性用来参照最近的form。
为了示范form特性,我们要做的工作将分解为JSP,Cell和Controller。
下面列出的是checkbox示例的完整代码。想要强调的主要事情是表标签form属性设置为presForm,它参照被称为presForm的form元素。
同时请注意表标签的autoIncludeParameters属性。进行排序、过滤、分页时,默认的eXtremeTable将保持所有传至JSP页面的参数。 这个特性对于内部其他的form进行排序、过滤、分页时,用于高效复制form元素同样有效。可以设置 autoIncludeParameters属性为false来固定它。
在这个form使用id属性是因为xhtm标准的要求,同时你也可以使用form的name属性。
<form id="presForm" action="<c:url value="selectedPresidentsListedController.run"/>" method="post"> Enter your name: <input type="text" name="userName" style="font-family:verdana,arial,helvetica,sans-serif;font-size:11px;" value="<c:out value="${param.userName}"/>" /> <ec:table items="presidents" action="${pageContext.request.contextPath}/selectedPresidentsController.run" view="compact" imagePath="${pageContext.request.contextPath}/images/table/compact/*.gif" rowsDisplayed="8" autoIncludeParameters="false" form="presForm" > <ec:exportPdf fileName="output.pdf" tooltip="Export PDF" headerColor="black" headerBackgroundColor="#b6c2da" headerTitle="Presidents" /> <ec:row> <ec:column alias="checkbox" title=" " width="5px" filterable="false" sortable="false" viewsAllowed="compact" cell="selectedPresident" /> <ec:column property="fullName" title="Name"/> <ec:column property="nickName" /> <ec:column property="term" /> </ec:row> </ec:table> <input type="button" name="sel" class="button" value="List Selected Presidents" onclick="document.forms.presForm.submit();" /> <script type="text/javascript"> function setPresidentState(chkbx) { //make sure that always know the state of the checkbox if (chkbx.checked) { eval('document.forms.presForm.chkbx_' + chkbx.name).value='SELECTED'; } else { eval('document.forms.presForm.chkbx_' + chkbx.name).value='UNSELECTED'; } } </script> </form>
表标签form属性参照最近的form是你使用这个特性所必须知道的,为了更好的理解这个特性,介绍更多的关于内部实现技术的细节是值得的。
如果您不特意指定form属性,eXtremeTable自动在表附近包上一个form。所有表的动作例如:排序、过滤、分页将自动给一些隐藏的input元素赋值,然后提交这个form到表标签action属性设置的Aciton。 这非常有效,除非您想要将自己的form元素设置到表体,或者想将这个表放到别的form里。
表标签form属性参照最近的form,所有表的动作例如:排序、过滤、分页将自动给一些隐藏的input元素赋值,但是现在 最近form的action属性将要改变表标签的动作。这非常重要,因为:当排序、过滤、分页时,eXtremeTable能够从一个controller得到数据集合 ,但是提交这个form到别的controller来处理这个form时需要对用户的输入进行处理。然而,这些对于你使用表标签来说都是透明的。 就像你现在做的那样简单地设置表标签的action属性,然后设置相关的form到你想提交的位置。
示例的第一列是checkbox。因为这列不需要参照bean的属性,alias属性用来唯一地标识这列。你可以使用property 属性,但是alias属性使这列如何使用更清楚。alias属性还被用来当同样的属性被多列使用时唯一地标识一列。
您也许想知道定制的cell是如何通过名称selectedPresident被参照的(cell="selectedPresident")。这是一个 对eXtremeTable的preferences特性更强的使用。所有要做的就是在extremecomponents.properties文件中添加一个属性。 请参考Preferences来了解更多的信息
column.cell.selectedPresident=org.extremesite.cell.SelectedPresidentCell
column.cell.selectedPresident就是你定义的用来参照这个cell的名称。
当然你也可以使用这个Cell的全名来进行参照。
<ec:column alias="checkbox" title=" " width="5px" filterable="false" sortable="false" viewsAllowed="compact" cell="org.extremesite.cell.SelectedPresidentCell" />
在属性文件中定义参照更方便,它可以被任何JSP文件引用。如果类名或包名改变的话你只需要对一个地方进行修改。
JavaScript的setPresidentState()方法被定制cell用来设置每个checkbox元素的是否被选中。 设置一个隐藏元素的原因是为了获得浏览器的动作而不提交没有选中的checkbox。通过这个Controller将一直知道一个元素是否别选中。
定制的cell被用来生成checkbox,另外它也创建一个隐藏元素用来表示这个checkbox元素是否被选中。 当用户进行排序、过滤、分页时,被选中的数据集合将被放到session里。
getExportDisplay()方法没有返回值,因为治理只需要Html显示。
public class SelectedPresidentCell implements Cell { public String getExportDisplay(TableModel model, Column column) { return null; } public String getHtmlDisplay(TableModel model, Column column) { HtmlBuilder html = new HtmlBuilder(); CellBuilder.tdStart(html, column); try { Object bean = model.getCurrentRowBean(); String presidentId = BeanUtils.getProperty(bean, "presidentId"); Collection selectedPresidentsIds = (Collection)model.getContext().getSessionAttribute(SelectedPresidentsConstants.SELECTED_PRESIDENTS); if (selectedPresidentsIds != null && selectedPresidentsIds.contains(presidentId)) { html.input("hidden").name("chkbx_" + presidentId).value(SelectedPresidentsConstants.SELECTED).xclose(); html.input("checkbox").name(BeanUtils.getProperty(bean, "presidentId")); html.onclick("setPresidentState(this)"); html.checked(); html.xclose(); } else { html.input("hidden").name("chkbx_" + presidentId).value(SelectedPresidentsConstants.UNSELECTED).xclose(); html.input("checkbox").name(BeanUtils.getProperty(bean, "presidentId")); html.onclick("setPresidentState(this)"); html.xclose(); } } catch (Exception e) {} CellBuilder.tdEnd(html); return html.toString(); } }
提示:Spring框架的Controller和Struts框架的Action非常相像。
当在另外的form中使用eXtremeTable时,你可能有1个或2个controllers。当form被提交时,你需要一个controller 来处理用户的输入并重新定向到另外的JSP页面。当排序、过滤、分页时,你可能有另外的controller来得到表使用的数据集合并重定向会本页。或者你可以在同一个controller中分别处理。
checkbox示例里我使用一个controller来关联表标签的action属性。我也使用另外一个controller来关联form元素的动作。
这个controller负责调用SelectedPresidentsUtils来保存被选中的presidentIds到session里并回到同一页。
SelectedPresidentsUtils.saveSelectedPresidentsIDs(request); Collection presidents = presidentsService.getPresidents(); request.setAttribute("presidents", presidents);
这个controller负责通过presidentIds得到数据集并重定向到下一个Jsp页面
Collection selectedPresidentsIds = SelectedPresidentsUtils.saveSelectedPresidentsIDs(request); Collection selectedPresidents = SelectedPresidentsUtils.getSelectedPresidents(presidentsService.getPresidents(), selectedPresidentsIds); request.setAttribute("selected", selectedPresidents); request.getSession().removeAttribute(SelectedPresidentsConstants.SELECTED_PRESIDENTS);
我将列出保存presidentIds到session的代码。我经常被问到如何重新得到eXtremeTable中form元素的值。 它的原理是设置form输入元素名字属性值前面加上一些东西来唯一标识元素
本示例中我关心的是以chkbx开头参数的元素。chkbx后面是唯一的关联到checkbox的presidentId。它被用来判断这个checkbox是否别选中。
public static Collection saveSelectedPresidentsIDs(HttpServletRequest request) { Collection presidents = (Collection) request.getSession().getAttribute(SelectedPresidentsConstants.SELECTED_PRESIDENTS); if (presidents == null) { presidents = new ArrayList(); request.getSession().setAttribute(SelectedPresidentsConstants.SELECTED_PRESIDENTS, presidents); } Enumeration parameterNames = request.getParameterNames(); while (parameterNames.hasMoreElements()) { String parameterName = (String) parameterNames.nextElement(); if (parameterName.startsWith("chkbx_")) { String presidentId = StringUtils.substringAfter(parameterName, "chkbx_"); String parameterValue = request.getParameter(parameterName); if (parameterValue.equals(SelectedPresidentsConstants.SELECTED)) { if (!presidents.contains(presidentId)) { presidents.add(presidentId); } } else { presidents.remove(presidentId); } } } return presidents; }