问题:在ECSide列表中,每行都有select标签,用户在第一页进行各行的select选择之后,执行页面翻页操作,翻到第二页,再回到第一页时不能回显原先对各行select标签所做的选择。同样还有对列表进行排序、修改每页显示行数等打乱现有列表排列的操作。

环境描述:
   1)在ECSide列表中,保存用户所选择的每行select值,在用户执行页面翻页、排序、修改每页显示行数后,
   仍能回显出原先用户所选的select值。在用户点击提交或保存操作后能将用户在不同页所选的值提交到后台。
   2)select值的形式:用户所选值_本行记录的ID,例如:OptionValue_132
   3)确保ECSdie列表所在页面在执行页面翻页、排序、修改每页显示行数等操作时,整个页面局部刷新(如果整个页面刷新将会清除后面将要提到的一个JavaScript全局变量)。
   4)关闭ECSide列表标签中的隔页存值属性(autoIncludeParameters),使用该属性虽然可以达到隔页存值的目的,但不能回显原先用户所做的选择,并且在每次在执行页面翻页、排序、修改每页显示行数等操作时,不停的在创建hidden标签。

解决方案:
   1)在用户点击select进行选值时,将其所选值存入一个作为全局变量的数组,并且在往该数组中存入用户所选值时,以该行记录的ID作为数组下标,将对应的值存入数组。在用户对select值进行修改时,取出该ID对应的数组下标的值,进行修改操作,若置回请选择时,根据该行记录的ID作为索引找到数组中对应的值,清空数组中的该值。
   2)用户在执行页面翻页、排序、修改每页显示行数后,取出当页所有select对象,将这些select对象与数组中的值进行匹配,如果有对应下标的值将其回显出来。回显的时候需要从ecside.js中抽象出一个JavaScript函数用于在执行页面翻页、排序、修改每页显示行数后执行。
   对ecside.js的修改如下:
     (1)翻页:在ECSideUtil.gotoPage方法中取到新页面的HTML时(即执行ecsideObj.ajaxSubmit()之后)。
     (2)排序:在ECSideUtil.doSort方法中取到新页面的HTML时(即执行ecsideObj.ajaxSubmit()之后)。
     (3)修改每页显示多行:在ECSideUtil.changeRowsDisplayed方法中取到新页面的HTML时(即执行ecsideObj.ajaxSubmit()之后)。
     在以上三个方法之后添加如下代码:
  

try{ 
         //新的HMTL加载完后执行的函数    
         setAfterView(); 
      }catch(e){    
    
      } 
     这样我们在每个开发的页面,直接写function setAfterView(){}函数就可以实现要回显的操作了。 
   3)在用户点击“保存”或“提交”时,将数组中的值生成hidden连接到页面form中,提交到后台。 
       var tempHid=""; 
       if(saveSelValues!=null&&saveSelValues.length>0){//如果数组中有值 
           for(var i=parseInt(custIdTemp,10);i<saveSelValues.length;i++){ 
              if(saveSelValues[i]!=null){ 
           tempHid+="<input type='hidden' name='delIdTypeReas' value='" +i+"_"+saveSelValues[i]+ "'/>";//创建hidden标签,其中value值中的i(即数组的索引为每行记录的ID号)。 
           }           
           } 
           if(tempHid!=""){ 
           document.forms[0].insertAdjacentHTML("beforeEnd", tempHid);//将数组中的值生成hidden连接到页面form中 
           } 
       }


   4)在后台通过java的split("_")方法取出各ID所对应的用户所选值,之后再进行数据库操作。

备注:这种方式还适合于ECSide列表各中行的CheckBox、二级联动的select标签等的隔页存值问题。

参考实现:以下将以我在项目中开发的在ECSide列表中各行CheckBox和二级联动的select标签的隔页存值为例。
   描述:在EC列表中,第一列为CheckBox(进入列表页面默认都被选中),最后两列为一个二级联动的select标签(在CheckBox不被选中时,显示为可用,即默认为disabled)。
   代码如下:

CheckBox:(第一列) 
       <ec:column width="30" ellipsis="true" property="selectedCust" title="选择" sortable="false" > 
  <input type="checkbox" value="该行记录的ID" οnclick="abledSel(this)" checked="checked" typeId="该行记录的ID" name="delCustCheck"/> 
       </ec:column> 
    Select:(最后两列) 
       <select name="delType" typeId="该行记录的ID"  disabled="disabled" id="firstSel_该行记录的ID" οnchange="selSecondSel(this)">一级select菜单 
            <option value='1' selected="selected">一级菜单1</option> 
    <option value='2'>一级菜单2</option> 
       <select name="delRes"  typeId="该行记录的ID" disabled="disabled" id="secondSel_该行记录的ID" οnchange="saveSelValue(this)">二级select菜单 
            <option value='1_1'selected="selected">二级菜单1</option>  其中1_1中的第一个1表示一级菜单1的value值,第二个1表示二级菜单1的value值 
    <option value='1_2'>二级菜单2</option> 

    准备select菜单数据: 
         //准备一级菜单数据 
var delType=new Array(); 

delType[0]=new Array(); 
delType[0].push('一级菜单1'); 
delType[0].push('1'); 

delType[1]=new Array(); 
delType[1].push('一级菜单2'); 
delType[1].push('2'); 

//准备二级菜单数据 
var delReas=new Array(); 

delReas[0]=new Array(); 
delReas[0].push('二级菜单1'); 
delReas[0].push('1'); 
delReas[0].push('1'); //属于一级菜单1 

delReas[1]=new Array(); 
delReas[1].push('二级菜单2'); 
delReas[1].push('2'); 
delReas[1].push('1');  //属于一级菜单1 

delReas[2]=new Array(); 
delReas[2].push('二级菜单3'); 
delReas[2].push('3'); 
delReas[2].push('2');  //属于一级菜单2 
      JavaScript函数: 
//根据所选的一级菜单展示二级菜单 
          function selSecondSel(firstSel){ 
//取出一级菜单选择的是哪一个 
   var sel_Index = firstSel.selectedIndex; 
var temp=firstSel.options[sel_Index].value; 
var rowCode=firstSel.typeId; 
//设置二级菜单 
var sel_Obj_s=document.getElementById("secondSel_"+rowCode); 
sel_Obj_s.innerHTML=""; 
var flag=true; 
//alert(delReas.length); 
for(var i=0;i<delReas.length;i++){ 
  if(delReas[i][2]==temp){ 
  
   var oOption = document.createElement("OPTION"); 
sel_Obj_s.options.add(oOption); 
oOption.innerText = delReas[i][0]; 
oOption.value = delReas[i][2]+"_"+delReas[i][1]; 
if(flag){ 
      saveSelValues[rowCode]=delReas[i][2]+"_"+delReas[i][1]; 
  //  alert("4_saveSelValues["+rowCode+"]="+saveSelValues[rowCode]); 
    flag=false; 
} 

} 
} 
} 

//将客户列表的checkbox和select设置为可用 
function enableCheckSel(){ 

   var dcc=document.getElementsByName("delCustCheck"); 
   if(dcc!=null&&dcc.length>0){ 
      for(var i=0;i<dcc.length;i++){ 
          dcc[i].disabled=""; 
      } 
   } 
   if(saveSelValues!=null&&saveSelValues.length>0){ 
   var temp=document.getElementsByTagName("select"); 
       for(var i=0;i<temp.length;i++){ 
       if(temp[i].typeId!=undefined&&temp[i]!=null){ 
       if(saveSelValues[temp[i].typeId]!=undefined&&saveSelValues[temp[i].typeId]!=null&&saveSelValues[temp[i].typeId]!=""){ 
       temp[i].disabled=""; 
       } 
       } 
       } 
   } 
} 

//点击checkbox时执行 
var custIdTemp=0;//记录用户所点选过的最小值 
function abledSel(abledSel){   
    var as=abledSel.value; 
    if(parseInt(custIdTemp,10)==0){ 
       custIdTemp=as; 
    } 
    if(parseInt(as,10)<parseInt(custIdTemp,10)){ 
    custIdTemp=as; 
    } 
    var ce=abledSel.checked 
  
    var temp=new Array(); 
    temp[0]=document.getElementById("firstSel_"+as); 
    temp[1]=document.getElementById("secondSel_"+as); 
    if(temp.length>0){ 
       for(var i=0;i<temp.length;i++){  
              var selRowCode=as; 
              if(ce){//如果checkbox变为被选中,select标签不可用,清除数组中的存值 
              temp[i].disabled="true";              
              saveSelValues[selRowCode]=null;             
              }else{//如果checkbox变为没有被选中,将对应的select标签设置为可用,在数组中添加相应的select值 
             temp[i].disabled=""; 
             if(temp[i].id==("secondSel_"+selRowCode)){ 
             var sel_Index = temp[i].selectedIndex; 
var temp1=temp[i].options[sel_Index].value;             
             saveSelValues[selRowCode]=temp1;         
             } 
              }        
       } 
    } 
} 
//保存用户所选value值的数组 
var saveSelValues=new Array(); 
//保存用户所选的select值 
function saveSelValue(sel_Obj){ 
//取出一级菜单选择的是哪一个 
   var sel_Index = sel_Obj.selectedIndex; 
   var temp=sel_Obj.options[sel_Index].value; 
   var selRowCode=sel_Obj.typeId; 
   saveSelValues[selRowCode]=temp; 
} 
//在列表执行页面翻页、排序、修改每页显示行数等操作后执行回显 
function setAfterView(){ 
        if(saveSelValues!=null&&saveSelValues.length>0){ 
    var delCustCheck=document.getElementsByName("delCustCheck"); 
    for(var k=0;k<delCustCheck.length;k++){ 
    var i=delCustCheck[k].typeId; 
        if(saveSelValues[i]!=null){ 
           var firstSel=document.getElementById("firstSel_"+i); 
           var secondSel=document.getElementById("secondSel_"+i); 
           if(firstSel==undefined||firstSel==null||secondSel==undefined||secondSel==null){ 
               continue; 
           } 
               delCustCheck[k].checked=""; 
           if(firstSel!=undefined&&firstSel!=null&&secondSel!=undefined&&secondSel!=null){ 
           var temp=saveSelValues[i].split("_"); 
           firstSel.disabled=""; 
           secondSel.disabled=""; 
           firstSel.value=temp[0]; 
           temp=saveSelValues[i]; 
           selSecondSel(firstSel);//执行该函数后会将该二级菜单的第一个选项存入数组,注意将原值保留,修改数组中的该值 
           secondSel.value=temp; 
           saveSelValues[i]=temp; 
           } 
        } 
    } 
    } 
}



注意:JavaScript里数组的最大长度是: 4294967295,即2^32 - 1,数组的下标(即该行记录的ID)不要超过这个数。

补充:在实际开发过程中,有些记录的id是非常大的,好多都超过了10位数字,我想还是在列表中用rownumber做为每行记录的id来做数组的下标,这样即能保证每行记录有唯一的id,也能保证这个rownumber数字不会太大,毕竟在页面上显示的列表都是分页显示的,一般情况下再大能大到哪去呢?

以上仅为一个小小的参考实现,不过在效率上可能还有些欠缺,还有待优化,希望能启到抛砖引玉的作用。