Struts2默认theme是xhtml,它用表格来对表单中的控件进行排版。它也提供一个客户端的js验证功能,但是它的js脚本却有些问题,在某些情况下,前次验证的提示信息无法被清除,提示信息会不断的累积显示在屏幕上。而按照设计,每次提交表单时应只显示每次验证的出错信息。
它的客户端验证的流程大概是这样,用户提交表单时,对各个控件的输入按预先设置的规则进行验证,如果有问题,则清除表单里原有的出错提示信息,并写入新的提示。其设计的功能是把出错信息写表格里出错控件的上方,以便用户看得更加清楚。问题就出在其用来清除原出错信息的函数,其代码是这样的(在struts.jar的template/xhtml目录下可以找到):
1 function clearErrorMessages(form) {
2
3 var table = form.childNodes[1];
4 if( typeof table == "undefined" ) {
5 table = form.childNodes[0];
6 }
7
8 // clear out any rows with an "errorFor" attribute
9 var rows = table.rows;
10 var rowsToDelete = new Array();
11 if (rows == null){
12 return;
13 }
14
15 for(var i = 0; i < rows.length; i++) {
16 var r = rows[i];
17 if (r.getAttribute("errorFor")) {
18 rowsToDelete.push(r);
19 }
20 }
21
22 // now delete the rows
23 for (var i = 0; i < rowsToDelete.length; i++) {
24 var r = rowsToDelete[i];
25 table.deleteRow(r.rowIndex);
26 //table.removeChild(rowsToDelete[i]);
27 }
28 }
看这个函数的前三行,它试图取得form的第1个或第2个子节点,并把它作为table来处理(看接下来的几行)。要想清除表格里的错误信息,首先要取得表格本身,这没错,但是
如果第1个或第2个子节点不是table的话,脚本就会出错,造成原出错信息无法清除,这样每次提交后的提示信息就会累积在屏幕上。
要解决这个问题有两个办法:
- 写代码时要小心,保证form的第1或2个子节点是table,不要在生成table前加其他代码。
- 或,修改xhtml的validation.js,使它总能获得正确的table元素,重新打包到struts.jar。
刚看了一下Struts的JIRA,已经有人报告了这个问题(id
WW-1802),而且这个bug在2.1版本中已经解决了。