Добавить новые строки в модель jqGrid Treegrid - PullRequest
1 голос
/ 07 сентября 2011

Мы создали 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"}
]}

Ответы [ 2 ]

2 голосов
/ 12 сентября 2011

Демонстрация показывает, как использовать метод addChildNode для добавления узла дерева. Я добавил в данные JSON, которые вы опубликовали, часть "loaded":true, потому что в тесте я не использую серверные компоненты и хочу загрузить сетку дерева сразу.

Чтобы показать, что вы должны быть очень осторожны с идентификаторами новой добавленной строки, я добавил две демонстрационные кнопки: «Вставить узел дерева» и «Вставить узел дерева с уникальным rowid». Первая кнопка использует id = "1113" из данных, которые вы разместили. Один клик на кнопку работает правильно. второй щелчок вставит строки с дубликатами идентификаторов, что будет ошибкой. Ошибка вы можете увидеть по-разному в разных веб-браузерах. Вторая кнопка использует $.jgrid.randId() для генерации уникального rowid. Это, вероятно, не вариант в вашем сценарии, но он отлично работает в случае локальной сетки дерева (как в моей демонстрации).

Другая проблема заключается в том, что вы используете «parent»: «0» в своей демонстрации для корневых элементов. Правильным будет "parent":null или "parent":"null" (см. ответ ). Кроме того, свойство с именем "parent_id" будет игнорироваться. Я удалил из демо некоторые настройки, чтобы в сетке деревьев можно было использовать локальную сортировку.

1 голос
/ 14 сентября 2011

Мы решили эту проблему, расширив функциональность источника 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 для дочерних элементов этого узла. Таким образом, у нас всегда есть самые последние дети.

Наконец, мы исправили небольшую ошибку в getRowData(), которая не позволяла нам использовать ее для предоставления аргумента record либо expandNode(), либо нашему недавно созданному reloadNode(). Проблема заключалась в том, что поле _id_ в возвращении JSON никогда не создавалось и не заполнялось. Добавим, что в фиксированных 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 на новый, обновленный список из базы данных. Я собираюсь перенести это на jqGrid Github, если это возможно, поскольку функция reload может быть полезна для многих людей. Я разместил его здесь на случай, если он не будет одобрен.

...