ExtJS 3.4.0 - Build ComboBox with paging function

在ExtJS的下拉元件(ComboBox)中,如果資料量過多的話,可能會在第一次點擊時因為要

組成相關的DOM而導致瀏覽器執行指令碼過久的情形,可能會造成無回應的情況(如IE)。

因此在這邊簡單說明如何使用分頁功能,如此一來當點擊下拉時只需建立當下的分頁內容

,避免一次從後端傳回所有的資料。

前端程式

跟建立Grid一樣,您需要定義store、record,store為跟後端要求資料的儲存體,同時會定義

回傳的格式,並搭配record來取得mapping的資料。

var signnoColumns = Ext.data.Record.create([{name: "code_no", type:'String'},{name: "code_na", type:'String'}]);

var signnoStore = new Ext.data.Store({
        // load using HTTP
        url: "<%=request.getContextPath()%>/ActionServlet?action=composeComboBoxData",
  // 此讀取器可以解析JSON DATA, 並轉換成Record. Record需定義其欄位名稱與型別
        reader: new Ext.data.JsonReader({
            root: 'rows',
            totalProperty: 'totalRows',
            fields: signnoColumns
        }) 
    });

在這邊的record共定義了兩個欄位,分別為下拉選單的value(code_no)及text(code_na)

屬性root,表示JSON格式的key為rows,對應得值即為[{"code_no":"1", "code_na":"YES"},

{"code_no":"2", "code_na":"NO"}]

屬性totalProperty,表示JSON格式的key為totalRows,對應的為一總資料量的數值,如此才

可以提供元件算出頁數

接下來為定義ComboBox本身
var signnoCombo = new Ext.form.ComboBox({
  valueField: 'code_no',
  displayName: '員工編號',
  allowBlank: true,
  typeAhead: false,
  triggerAction: 'all',
  transform:'signno',
  forceSelection:false,
  resizable:true,
  width:100,
  listWidth:250,
  minChars:0,
  lazyRender:false,
  store: signnoStore,
  displayField: 'code_na',
  selectOnFocus:false,
  pageSize:5
 });

<input type="text" name="signno" id="signno" value="" size="10">

需注意的為設定屬性pageSize,在此設定為5表示一頁顯示五筆資料。而valueField、

displayField分別為code_no、code_na。

後端程式
public void composeComboBoxData(HttpServletRequest request){
  System.out.println("action composeComboBoxData");
  DatabaseDAO dao = new DatabaseDAO();
  JSONObject jsonData = new JSONObject();
  JSONArray rowArray = new JSONArray();
  int start = Integer.parseInt(request.getParameter("start"));
  int limit = Integer.parseInt(request.getParameter("limit"));
  System.out.println(start+"--"+limit);
  int index = 0;
  try {
   Map<String, String> rowdata = new HashMap<>();
   ResultSet rs = dao.getResultSet("select distinct signno code_no, signno code_na from paydetail");
   while(rs.next()){
    if(index >= start && start+limit > index){
     rowdata.put("code_no", rs.getString("code_no"));
     rowdata.put("code_na", rs.getString("code_na"));
     rowArray.put(new JSONObject(rowdata));
    }
    index++;
   }
   
   jsonData.put("rows", rowArray);
   jsonData.put("totalRows", index);
   
   outputResponse(jsonData.toString());
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } finally{
   try {
    dao.releaseConnection();
   } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }

在這邊要注意的是從前端固定會傳送參數start、limit,如您第一次點下拉,會傳送start => 0

、limit => 5的值到後端。此時您就可以依據查詢出來的資料集(ResultSet),來進一步組rows

key要對應的資料(應該為前5筆),totalRows要塞的是整體的數量。所以,當您點擊下一頁時

,start => 5、limit => 5,以此類推。在這邊的寫法會在每一次進入composeComboBoxData時

重新作查詢,您可以修改成第一次查詢時存進一List內,到時在下一次進入時直接針對該List

取得需要的資料區間即可,這樣就不用每一次查詢資料庫了。最後進行response輸出。



留言