2011-09-07 4 views
1

분기가 폴더이고 리프가 파일 인 파일 시스템을 나타내는 jqGrid TreeGrid가 작성되었습니다.을 사용하여 새 "파일"을 만들기 위해 TreeGrid에서 기능을 구현했습니다. 그러나 새 폴더를 만드는 기능을 추가하려고합니다. 우리의 스크립트는 새로운 폴더를 생성하지만 TreeGrid에 페이지가 다시로드되지 않는 한 즉시 표시되지 않습니다. 그러나 TreeGrid를 다시로드하면 모든 폴더가 축소되므로 특히 성가신 일입니다.jqGrid에 새 행 추가 Treegrid 모델

TreeGrid의 노드를 선택적으로 새로 고치거나 기능이 추가 된 새 분기를 추가 할 수 있습니까? addJSONData에 대한 일부 문서를 보았지만이 함수를 사용하면 새로 고칠 때까지 TreeGrid가 완전히 제거됩니다. 또한 addChildNode을 사용하여 특정 속성을 변경하려고 시도했으며 DOM 조작을 사용하여 행에 수동으로 추가하려고했습니다. 그러나이 두 가지 방법 모두 삽입 된 노드를 손상시킵니다.

편집 :

ret = {"error":"","total":1,"page":1,"records":1,"rows":[{"id":"1113","name":"test","uri":"accounting\/test\/","parent":1,"isLeaf":false,"expanded":true,"loaded":true}]} 

내가 사용에 추가하려고 :

grid[0].addJSONData(ret); 

초기를 A는 새 폴더 JSON 요청을 반환

var grid = $("#grid"); 
grid.jqGrid({ 
    treeGrid: true, 
    treeGridModel: "adjacency", 
    ExpandColumn: 'name', 
    ExpandColClick: true, 
    url:"", 
    datatype:"json", 
    colNames:['id','Name','Authorization','Views','Uri'], 
    colModel:[ {name:'id', index:'id', hidden:true, key:true}, 
       {name:'name', index:'name', sorttype:"text", width:3, sortable:false}, 
       {name:'auth',index:'auth', sorttype:"text", sortable:false, hidden:true}, 
       {name:'views',index:'views', sorttype:"integer", width:1, sortable:false, align:"center"}, 
       {name:'uri',index:'uri',sorttype:'text',sortable:false,hidden:true}], 
    jsonReader:{ root:"rows" 
       ,page:"page" 
       ,total:"total" 
       ,records:"records" 
       ,repeatitems:false 
       ,cell:"" 
       ,id:"0" 
       ,userdata:"" 
       }, 
    multiselect:false, 
    autowidth:true, 
    height:"auto", 
    sortable:false, 
    toppager:true, 
    hidegrid: false, 
    loadui: 'block', 
    pager:"#grid_pager", 
    caption: "Files", 
}); 

이 같이 보입니다 로드 된 데이터는 JSON 형식으로 전송됩니다.

{"rows":[ 
    {"id":"1","uri":"afolder\/","parent_id":"0","name":"afolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"4","uri":"bfolder\/","parent_id":"0","name":"bfolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"7","uri":"cfolder\/","parent_id":"0","name":"cfolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"20","uri":"dfolder\/","parent_id":"0","name":"dfolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"48","uri":"efolder\/","parent_id":"0","name":"efolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"179","uri":"ffolder\/","parent_id":"0","name":"ffolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"182","uri":"gfolder\/","parent_id":"0","name":"gfolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"186","uri":"hfolder\/","parent_id":"0","name":"hfolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"201","uri":"ifolder\/","parent_id":"0","name":"ifolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"239","uri":"jfolder\/","parent_id":"0","name":"jfolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"253","uri":"kfolder\/","parent_id":"0","name":"kfolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"262","uri":"lfolder\/","parent_id":"0","name":"lfolder","level":0,"parent":"0","isLeaf":"false"}, 
    {"id":"274","uri":"mfolder\/","parent_id":"0","name":"mfolder","level":0,"parent":"0","isLeaf":"false"} 
]} 
+0

코드를 추가하면 많은 추가 정보를 얻을 수 있으므로 항상 도움이됩니다. 당신이 사용하는 TreeGrid에 대해 더 많이 설명해 주시겠습니까? 로컬 데이터를 사용하거나 서버에서 데이터를로드합니까? 한 번에 전체 그리드를로드합니까 아니면 상위 노드를 확장 할 때 하위 노드를로드합니까? 네가 가지고있는 그리드 모델 : 중첩 세트 모델 또는 인접 모델. 트리 그리드에 추가해야하는 새 폴더에 대한 정보를 얻는 방법은 무엇입니까? 일부 페이지 입력 컨트롤의 정보가 채워지거나 서버에서로드되는 경우? – Oleg

+0

인접성 모델을 사용하고 노드가 확장됨에 따라 MySQL 데이터베이스에서 JSON 요청으로 데이터를 조각으로 가져옵니다. 새 폴더에 대한 정보는 AJAX 요청을 통해 데이터베이스에 새 폴더 레코드를 만드는 JSON 요청에서 반환됩니다. 코드 추가. – shmeeps

+0

미안하지만 아직도 상황을 이해하지 못합니다. 먼저 트리 그리드에 서버의 데이터를 채 웁니다. 사용자가 트리 노드를 클릭하면 노드의 하위 노드가 서버에서로드됩니다. 어떻게 한 노드 (폴더)를 추가해야합니까? 왜 새 폴더의 데이터에 부모 (' "parent": 1')가 들어 있습니까? 아마도 그리드를 채우는 방법을 이해하는 것이 주된 질문에 연결되어있을 것입니다. 당신은 "데이터를 조각으로"얻으려고했지만 데이터베이스에서는 썼다. 나는 그런 상황을 상상할 수 없다. 데이터베이스에서 SELECT를하면 모든 결과를 그리드로 보낼 수 있습니다. 그렇지? – Oleg

답변

1

jqGrid 소스의 기능을 확장하여이 문제를 해결했습니다. 먼저 특정 폴더의 모든 하위 노드 (폴더/분기 및 파일/잎 모두)를 삭제할 수있는 함수를 작성하여 다시로드하여 최신 하위 세트를 가져올 수 있습니다. 이 함수는 delTreeNode()처럼 rowid의 정수를 사용합니다.

delChildren : function (rowid) { 
    return this.each(function() { 
     var $t = this, rid = $t.p.localReader.id, 
     left = $t.p.treeReader.left_field, 
     right = $t.p.treeReader.right_field, myright, width, res, key; 
     if(!$t.grid || !$t.p.treeGrid) {return;} 
     var rc = $t.p._index[rowid]; 
     if (rc !== undefined) { 
      // nested 
      myright = parseInt($t.p.data[rc][right],10); 
      width = myright - parseInt($t.p.data[rc][left],10) + 1; 
      var dr = $($t).jqGrid("getFullTreeNode",$t.p.data[rc]); 
      if(dr.length>0){ 
       for (var i=0;i<dr.length;i++){ 
        if(dr[i][rid] != rowid) 
         $($t).jqGrid("delRowData",dr[i][rid]); 
       } 
      } 
      if($t.p.treeGridModel === "nested") { 
       // ToDo - update grid data 
       res = $.jgrid.from($t.p.data) 
        .greater(left,myright,{stype:'integer'}) 
        .select(); 
       if(res.length) { 
        for(key in res) { 
         res[key][left] = parseInt(res[key][left],10) - width ; 
     } 
       } 
       res = $.jgrid.from($t.p.data) 
        .greater(right,myright,{stype:'integer'}) 
        .select(); 
       if(res.length) { 
        for(key in res) { 
         res[key][right] = parseInt(res[key][right],10) - width ; 
        } 
       } 
      } 
     } 
    }); 
}, 

그런 다음 특정 노드 (폴더)를 강제로 다시로드하는 기능을 만들었습니다.

reloadNode: function(rc) { 
     return this.each(function(){ 
      if(!this.grid || !this.p.treeGrid) {return;} 

      var rid = this.p.localReader.id; 

      $(this).jqGrid("delChildren", rc[rid]); 

      var expanded = this.p.treeReader.expanded_field, 
      parent = this.p.treeReader.parent_id_field, 
      loaded = this.p.treeReader.loaded, 
      level = this.p.treeReader.level_field, 
      lft = this.p.treeReader.left_field, 
      rgt = this.p.treeReader.right_field; 

      var id = $.jgrid.getAccessor(rc,this.p.localReader.id); 
      var rc1 = $("#"+id,this.grid.bDiv)[0]; 

      rc[expanded] = true; 
      $("div.treeclick",rc1).removeClass(this.p.treeIcons.plus+" tree-plus").addClass(this.p.treeIcons.minus+" tree-minus"); 
      this.p.treeANode = rc1.rowIndex; 
      this.p.datatype = this.p.treedatatype; 
      if(this.p.treeGridModel == 'nested') { 
       $(this).jqGrid("setGridParam",{postData:{nodeid:id,n_left:rc[lft],n_right:rc[rgt],n_level:rc[level]}}); 
      } else { 
       $(this).jqGrid("setGridParam",{postData:{nodeid:id,parentid:rc[parent],n_level:rc[level]}}); 
      } 
      $(this).trigger("reloadGrid"); 
      rc[loaded] = true; 
      if(this.p.treeGridModel == 'nested') { 
       $(this).jqGrid("setGridParam",{postData:{nodeid:'',n_left:'',n_right:'',n_level:''}}); 
      } else { 
       $(this).jqGrid("setGridParam",{postData:{nodeid:'',parentid:'',n_level:''}}); 
      } 
     }); 
    }, 

expandNode()과 동일한 노드로 시작하는 확장 된 경우는 확인하지 않고, 힘은 그 노드의 자식 요소에 대한 AJAX 요청을 보내 그 용으로 저장]을 선택합니다. 이렇게하면, 우리는 항상 최신 자녀를 갖게됩니다.

마지막으로, 우리는 expandNode()하거나 새로 만든 reloadNode() 중 하나에 record 인수를 제공하는 데 사용에서 우리를 방지하는 getRowData()에 작은 버그가 수정되었습니다. 문제는 JSON 반환의 _id_ 필드가 생성되거나 채워지지 않은 것입니다. 고정 된 값으로 추가하기 expandNode()reloadNode() 다음은 변경된 소스입니다. 이상적은 아니지만 작동합니다. 마지막으로

getRowData : function(rowid) { 
    var res = {}, resall, getall=false, len, j=0; 
    this.each(function(){ 
     var $t = this,nm,ind; 
     if(typeof(rowid) == 'undefined') { 
      getall = true; 
      resall = []; 
      len = $t.rows.length; 
     } else { 
      ind = $t.rows.namedItem(rowid); 
      if(!ind) { return res; } 
      len = 2; 
     } 
     while(j<len){ 
      if(getall) { ind = $t.rows[j]; } 
      if($(ind).hasClass('jqgrow')) { 
       $('td',ind).each(function(i) { 
        nm = $t.p.colModel[i].name; 
        if (nm !== 'cb' && nm !== 'subgrid' && nm !== 'rn') { 
         if($t.p.treeGrid===true && nm == $t.p.ExpandColumn) { 
          res[nm] = $.jgrid.htmlDecode($("span:first",this).html()); 
         } else { 
          if($t.p.colModel[i].key != undefined && $t.p.colModel[i].key == true) 
          { 
           try { 
            res["_" + nm + "_"] = $.unformat(this,{rowId:ind.id, colModel:$t.p.colModel[i]},i); 
           } catch (e){ 
            res["_" + nm + "_"] = $.jgrid.htmlDecode($(this).html()); 
           } 
          } 
          try { 
           res[nm] = $.unformat(this,{rowId:ind.id, colModel:$t.p.colModel[i]},i); 
          } catch (e){ 
           res[nm] = $.jgrid.htmlDecode($(this).html()); 
          } 
         } 
        } 
       }); 
       if(getall) { resall.push(res); res={}; } 
      } 
      j++; 
     } 
    }); 
    return resall ? resall: res; 
}, 

, 우리는 다음과 같은

{{"id":"1267", "name":"test15", "uri":"sample1\/test15\/", "parent_id":1, "parent":1, "isLeaf":false} 

우리는

var parentid = ret.rows[0].parent; 

var parent = grid.jqGrid('getRowData', parentid); 

grid.jqGrid('reloadNode', parent); 

기능 등의 기능을 호출 할 폴더를 생성에서 JSON 반환 개체, 모두 함께 다음과 같이 당겨 것 parent의 모든 자식 노드를 삭제 한 다음 데이터베이스에서 새로 업데이트 된 목록에 대한 AJAX 요청을 보냅니다. 가능한 한 많은 사람들에게 유용한 reload 함수가 있기 때문에 이것을 jqGrid Github에 푸시 할 것입니다. 승인되지 않은 경우를 대비하여 여기에 게시했습니다.

+0

재미 있겠지만, 사용하기 전에 upvoting을 사용하면 내 대답에 주석을 달 수 있습니다. 또한 노드의 삭제 * (delTreeNode')에 대한 답을 설명하지만 노드에 대한 질문이 * 추가되었습니다. 아마도'delTreeNode'와 관련하여 설명을 건너 뛰고 해결할 문제가있을 것입니다. 일반적으로 새로운 노드를 추가해야하는 경우 * 기존 자식 노드를 삭제하는 것은 잘못되었습니다. – Oleg

2

The demo은 트리 노드를 추가하는 방법을 addChildNode하는 방법을 보여줍니다. 나는 아무 서버 구성 요소도 테스트하지 않고 한 번에 트리 그리드를로드하려고하므로 "loaded":true 부분을 게시 한 JSON 데이터에 추가했습니다.

새로 추가 된 행의 ID에주의해야한다는 것을 보여주기 위해 데모에 두 개의 버튼 ("트리 노드 삽입"및 "고유 한 행 ID가있는 트리 노드 삽입")를 추가했습니다. 첫 번째 버튼은 게시 한 데이터에서 id = "1113"을 사용합니다. 한 번의 클릭으로 버튼이 제대로 작동합니다. 두 번째 클릭은 ID 중복이있는 행을 삽입하여 오류가 발생합니다. 다른 웹 브라우저에서 볼 수있는 오류입니다. 두 번째 단추는 $.jgrid.randId()을 사용하여 고유 한 rowid를 생성합니다. 시나리오에서는 옵션이 아닐 수도 있지만 로컬 트리 그리드 (내 데모와 동일)의 경우 완벽하게 작동합니다.

또 다른 문제는 루트 요소에 대한 데모에서 "parent": "0"을 사용한다는 것입니다. 올바른 내용은 "parent":null 또는 "parent":"null"입니다 (the answer 참조). 또한 이름이 "parent_id" 인 속성은 무시됩니다. 데모에서 일부 설정을 제거하여 로컬 정렬을 트리 그리드에서 사용할 수 있도록했습니다.