1

ブランチがフォルダーで、リーフがファイルであるファイルシステムを表す jqGrid TreeGrid を作成しました。TreeGrid 内に機能を実装し、これを使用して新しい「ファイル」を作成すると、addChildNode十分に機能します。ただし、新しいフォルダーを作成する機能も追加したいと考えています。新しいフォルダーを作成するスクリプトは機能しますが、フォルダーまたはページがリロードされない限り、それらは TreeGrid にすぐには表示されません。ただし、TreeGrid をリロードすると、すべてのフォルダーが折りたたまれるので、特に面倒です。

TreeGrid のノードを選択的に更新する方法、または機能する新しいブランチを追加する方法はありますか? に関する部分的なドキュメントを見てきましたaddJSONDataが、この関数を使用すると、更新されるまで TreeGrid が完全に消去されます。また、特定のプロパティを使用addChildNodeおよび変更しようとしました。また、DOM 操作を使用して手動で行を追加しようとしました。ただし、これらの方法は両方とも、挿入されたノードを壊します。

編集:

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 要求は、次のようになります。

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);

ロードされる初期データは 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"}
]}
4

2 に答える 2

2

このデモは、 addChildNodeメソッドを使用してツリー ノードを追加する方法を示しています。"loaded":trueテストではサーバーコンポーネントを使用せず、ツリーグリッドを一度にロードしたいので、投稿したJSONデータを追加しました。

新しく追加された行の ID に注意する必要があることを示すために、デモに「ツリー ノードを挿入」と「一意の行 ID を持つツリー ノードを挿入」という 2 つのボタンを追加しました。最初のボタンは、投稿したデータの id="1113" を使用します。ボタンのワンクリックは正しく機能します。2 回目のクリックで、ID が重複している行が挿入され、エラーになります。表示されるエラーは、Web ブラウザーによって異なります。2 番目のボタンは$.jgrid.randId()、一意の行 ID を生成するために使用します。あなたのシナリオではおそらくオプションではありませんが、ローカルツリー グリッドの場合には完璧に機能します (私のデモのように)。

別の問題は、ルート要素のデモで "parent":"0" を使用することです。正解は"parent":nullorです"parent":"null"(答えを見てください)。さらに、その名前のプロパティは"parent_id"無視されます。ツリーグリッドでローカルソートを使用できるように、デモからいくつかの設定を削除しました。

于 2011-09-12T12:43:40.017 に答える
1

jqGridソースの機能を拡張することで、この問題を解決しました。最初に、特定のフォルダー(フォルダー/ブランチとファイル/リーフの両方)のすべての子ノードを削除できる関数を作成しました。これにより、それらを再ロードして、最新の子のセットを取得できます。rowidこの関数は、と同じように整数を取りますdelTreeNode()

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要求を送信するように強制するという点でsaveと同じです。このように、私たちは常に最新の子供たちを持っています。

最後に、の小さなバグを修正しましたgetRowData()。これにより、のいずれかまたは新しく作成したにrecord引数を提供するためにそれを使用できなくなりました。問題は、JSONリターンのフィールドが作成または入力されなかったことです。両方を修正して追加すると、変更されたソースは次のとおりです。理想的ではありませんが、機能します。expandNode()reloadNode()_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;
},

最後に、次のようなフォルダーの作成からのJSONリターンオブジェクトを使用して、これをすべてまとめます。

{{"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);

関数は、親のすべての子ノードを削除してから、データベースから新しい更新されたリストに対するAJAXリクエストを送信します。reload関数は多くの人にとって役立つかもしれないので、可能であればこれをjqGridGithubにプッシュします。承認されない場合に備えて、ここに投稿しました。

于 2011-09-14T15:50:41.923 に答える