Translate

2019년 6월 13일 목요일

[jqGrid] populate 메소드 설명







환경: jqGrid v4.7.1 이하 (무료버전)



개발자가 해당 메소드를 직접 호출할일은 일반적으로 없겠지만 jqGrid 내부로직을 공부하다보면 필수적으로 실행되며, 중요한 역할을 하는 메소드라서 이렇게 알아본다.

populate 메소드는 다음의 상황에서 사용되어진다.
 1) jqGrid 초기화(initialization) 시점
 2) reloadGrid - 링크
 3) sortGrid 메소드 (sortData 메소드 수행)
 4) onPaging 이벤트 - 링크
 5) 그리드의 헤더(th) 클릭 시 (sortData 메소드 수행)


https://github.com/tonytomov/jqGrid/blob/v4.7.1/js/jquery.jqGrid.js#L1990
1004lucifer
/**
 * populate
 * @param npage 동적스크롤 그리드 사용하는 경우 값이 넘어옴
 */
populate = function (npage) {
  // Request progressBar 가 보여지지 않을 때
  if (!ts.grid.hDiv.loading) {
    var pvis = ts.p.scroll && npage === false,
      prm = {}, dt, dstr, pN = ts.p.prmNames;
    
    // page값이 1보다 적은경우 1로 셋팅
    if (ts.p.page <= 0) { ts.p.page = Math.min(1, ts.p.lastpage); }
    
    if (pN.search !== null) { prm[pN.search] = ts.p.search; } if (pN.nd !== null) { prm[pN.nd] = new Date().getTime(); }
    if (pN.rows !== null) { prm[pN.rows] = ts.p.rowNum; } if (pN.page !== null) { prm[pN.page] = ts.p.page; }
    if (pN.sort !== null) { prm[pN.sort] = ts.p.sortname; } if (pN.order !== null) { prm[pN.order] = ts.p.sortorder; }
    if (ts.p.rowTotal !== null && pN.totalrows !== null) { prm[pN.totalrows] = ts.p.rowTotal; }

    // lc 변수에 loadComplete 이벤트 저장
    var lcf = $.isFunction(ts.p.loadComplete), lc = lcf ? ts.p.loadComplete : null;

    var adjust = 0;
    npage = npage || 1;

    // 동적스크롤 그리드 사용하는 경우
    if (npage > 1) {
      if (pN.npage !== null) {
        prm[pN.npage] = npage;
        adjust = npage - 1;
        npage = 1;
      } else {
        lc = function (req) {
          ts.p.page++;
          ts.grid.hDiv.loading = false;
          if (lcf) {
            ts.p.loadComplete.call(ts, req);
          }
          populate(npage - 1);
        };
      }
    } else if (pN.npage !== null) {
      delete ts.p.postData[pN.npage];
    }

    // 데이터 그룹화(Data grouping) 그리드 사용하는 경우
    if (ts.p.grouping) {
      $(ts).jqGrid('groupingSetup');
      var grp = ts.p.groupingView, gi, gs = "";
      for (gi = 0; gi < grp.groupField.length; gi++) {
        var index = grp.groupField[gi];
        $.each(ts.p.colModel, function (cmIndex, cmValue) {
          if (cmValue.name === index && cmValue.index) {
            index = cmValue.index;
          }
        });
        gs += index + " " + grp.groupOrder[gi] + ", ";
      }
      prm[pN.sort] = gs + prm[pN.sort];
    }
    $.extend(ts.p.postData, prm);
    var rcnt = !ts.p.scroll ? 1 : ts.rows.length - 1;

    // jqGridBeforeRequest 트리거 이벤트 호출
    var bfr = $(ts).triggerHandler("jqGridBeforeRequest");
    if (bfr === false || bfr === 'stop') { return; }

    // datatype: function 타입인경우 호출
    if ($.isFunction(ts.p.datatype)) { ts.p.datatype.call(ts, ts.p.postData, "load_" + ts.p.id, rcnt, npage, adjust); return; }

    // beforeRequest 이벤트 호출
    if ($.isFunction(ts.p.beforeRequest)) {
      bfr = ts.p.beforeRequest.call(ts);
      if (bfr === undefined) { bfr = true; }
      if (bfr === false) { return; }
    }

    // datatype 종류에 따라 로직 분류
    dt = ts.p.datatype.toLowerCase();
    switch (dt) {
      case "json":
      case "jsonp":
      case "xml":
      case "script":
        // Ajax 호출
        $.ajax($.extend({
          url: ts.p.url,
          type: ts.p.mtype,
          dataType: dt,
          data: $.isFunction(ts.p.serializeGridData) ? ts.p.serializeGridData.call(ts, ts.p.postData) : ts.p.postData,
          success: function (data, st, xhr) {
            // beforeProcessing 이벤트 호출
            if ($.isFunction(ts.p.beforeProcessing)) {
              if (ts.p.beforeProcessing.call(ts, data, st, xhr) === false) {
                endReq();
                return;
              }
            }
            // 데이터를 그리드에 추가
            if (dt === "xml") { addXmlData(data, ts.grid.bDiv, rcnt, npage > 1, adjust); }
            else { addJSONData(data, ts.grid.bDiv, rcnt, npage > 1, adjust); }
            // jqGridLoadComplete 트리거 이벤트 호출
            $(ts).triggerHandler("jqGridLoadComplete", [data]);
            // loadComplete 이벤트 호출
            if (lc) { lc.call(ts, data); }
            // jqGridAfterLoadComplete 트리거 이벤트 호출
            $(ts).triggerHandler("jqGridAfterLoadComplete", [data]);
            if (pvis) { ts.grid.populateVisible(); }
            if (ts.p.loadonce || ts.p.treeGrid) { ts.p.datatype = "local"; }
            data = null;
            if (npage === 1) { endReq(); }
          },
          error: function (xhr, st, err) {
            // loadError 이벤트 호출
            if ($.isFunction(ts.p.loadError)) { ts.p.loadError.call(ts, xhr, st, err); }
            if (npage === 1) { endReq(); }
            xhr = null;
          },
          beforeSend: function (xhr, settings) {
            var gotoreq = true;
            // loadBeforeSend 이벤트 호출
            if ($.isFunction(ts.p.loadBeforeSend)) {
              gotoreq = ts.p.loadBeforeSend.call(ts, xhr, settings);
            }
            if (gotoreq === undefined) { gotoreq = true; }
            if (gotoreq === false) {
              return false;
            }
            beginReq();
          }
        }, $.jgrid.ajaxOptions, ts.p.ajaxGridOptions));
        break;
      case "xmlstring":
        beginReq();
        dstr = typeof ts.p.datastr !== 'string' ? ts.p.datastr : $.parseXML(ts.p.datastr);
        // 데이터를 그리드에 추가
        addXmlData(dstr, ts.grid.bDiv);
        // jqGridLoadComplete 트리거 이벤트 호출
        $(ts).triggerHandler("jqGridLoadComplete", [dstr]);
        // loadComplete 이벤트 호출
        if (lcf) { ts.p.loadComplete.call(ts, dstr); }
        // jqGridAfterLoadComplete 트리거 이벤트 호출
        $(ts).triggerHandler("jqGridAfterLoadComplete", [dstr]);
        ts.p.datatype = "local";
        ts.p.datastr = null;
        endReq();
        break;
      case "jsonstring":
        beginReq();
        if (typeof ts.p.datastr === 'string') { dstr = $.jgrid.parse(ts.p.datastr); }
        else { dstr = ts.p.datastr; }
        // 데이터를 그리드에 추가
        addJSONData(dstr, ts.grid.bDiv);
        // jqGridLoadComplete 트리거 이벤트 호출
        $(ts).triggerHandler("jqGridLoadComplete", [dstr]);
        // loadComplete 이벤트 호출
        if (lcf) { ts.p.loadComplete.call(ts, dstr); }
        // jqGridAfterLoadComplete 트리거 이벤트 호출
        $(ts).triggerHandler("jqGridAfterLoadComplete", [dstr]);
        ts.p.datatype = "local";
        ts.p.datastr = null;
        endReq();
        break;
      case "local":
      case "clientside":
        beginReq();
        ts.p.datatype = "local";
        var req = addLocalData();
        // 데이터를 그리드에 추가
        addJSONData(req, ts.grid.bDiv, rcnt, npage > 1, adjust);
        // jqGridLoadComplete 트리거 이벤트 호출
        $(ts).triggerHandler("jqGridLoadComplete", [req]);
        // loadComplete 이벤트 호출
        if (lc) { lc.call(ts, req); }
        // jqGridAfterLoadComplete 트리거 이벤트 호출
        $(ts).triggerHandler("jqGridAfterLoadComplete", [req]);
        if (pvis) { ts.grid.populateVisible(); }
        endReq();
        break;
    }
  }
}


여기서 주의깊게 봐야 하는부분은 datatype 에 상관없이
beforeRequest, loadComplete 이벤트가 무조건 호출된다는 점이다.

특히 loadComplete 이벤트는 그리드에 데이터가 모두 채워진 다음에 수행이 되기 때문에 페이징 번호를 수동으로 처리하는 경우에 loadComplete에 넣어두는게 좋다.



댓글 없음 :

댓글 쓰기