Можно ли изменить colModel после загрузки данных с помощью jqgrid? - PullRequest
4 голосов
/ 22 марта 2011

У меня есть jqGrid, где мне нужно изменить модель после загрузки данных, но до того, как они будут проанализированы в сетке. Другими словами, я думаю, что хочу сделать это в обработчике loadComplete. Я вижу такой подход: Установка JQGrid colName и colModel из данных JSON , но у меня уже есть куча сеток, которые используют подход «загрузка данных с jqGrid», а не «предварительная загрузка данных» и передать его в jqGrid ", который использовался там, и я надеюсь избежать перекодирования или сделать его другим.

(Скрывать и показывать скрытые столбцы тоже нецелесообразно.)

Возможно ли это?

Подробнее:

По сути, я не знаю, какие столбцы мне нужны, пока не увижу данные. Скажем, я показываю трафик по штатам:

Date      CA     WA     NY    MN
4/20      100    90     85    72
4/21       95    85     89    70

Существует только место для отображения четырех состояний, но в данных может быть намного больше (или их может быть меньше), поэтому я хочу, чтобы они были перечислены в порядке трафика. Прямо сейчас данные поступают как:

{
date : 4-20,
ca : 100,
wa : 90,
ny : 85,
mn : 72
hi : 56,
il : 30
},
{
date : 4-21,
ca : 95,
wa : 85, // note: for a given row, a column might be relatively lower
ny : 89, // than another. The column order is based on the overall
mn : 70
hi : 60,
il : 45
}

или это может быть:

{
date : 4-20,
ny : 110,
hi : 95,
il : 90,
wa : 80
}

Я пытался настроить столбцы, такие как state1, state2, state3, state4, а затем с помощью jsonmap переназначить их, но это не сработало.

loadonce = true, тип данных = json

1 Ответ

7 голосов
/ 23 марта 2011

Я нашел один способ, который, кажется, работает хорошо.

Идея моего решения заключается в следующем.Вы используете colModel с множеством скрытых столбцов с фиктивными именами, такими как «cm0», «cm1», «cm2», ... Все столбцы содержат те же данные, что и в вашем случае.Для более легкого заполнения данных я использую шаблоны столбцов, существующие с jqGrid 3.8.2:

var mygrid=jQuery("#list"),
    cmIntTemplate = {
        width:50,
        sorttype:"int",
        formatter:"integer",
        align:"right",
        hidden:true
    },
    cm = [
        // here we define the first columns which we always has
        // the list can be empty or has some columns with
        // the properties other as the rest (without cmIntTemplate)
        {name:"date",label:"Date",key:true,width:100, fixed:true,
         formatter:'date',formatoptions:{srcformat:"m-d",newformat:"m/d"}}
    ], maxCol = 30, dummyColumnNamePrefix = "cm";

// Add dummy hidden columns. All the columns has the same template
for (i=0;i<maxCol;i++) {
    cm.push({name:dummyColumnNamePrefix+i,template:cmIntTemplate});
}

После этого я создаю jqGrid стандартным способом, но с jsonReader, в котором используется page как функция :

jsonReader: {
    repeatitems: false,
    page: function (obj) {
        // ------------------------
        // here I add the main code
        // ------------------------
        return obj.page;
    }
}

Функция из jsonReader.page возвращает то же значение, что и по умолчанию jsonReader, но я использую способ с функцией, потому что функция будет вызываться непосредственно передчтение основного содержимого данных JSON.Внутри кода я получаю первую строку данных и использую их имена свойств, чтобы заполнить jsonmap свойство соответствующего столбца и установить имя столбца.Кроме того, я сделал несколько фиктивных столбцов, необходимых для отображения всех данных JSON, а остальные фиктивные столбцы скрыты.Последнее, что нужно сделать, это исправить ширину сетки, которая была рассчитана ранее.Таким образом, сетка будет выглядеть следующим образом:

enter image description here

или как это

enter image description here

зависит от входных данных JSON.

Код функции page следующий:

page: function (obj) {
    var rows = obj.rows, colModel = mygrid[0].p.colModel,
        cmi, iFirstDummy, firstRow, prop,
        orgShrinkToFit, isFound,
        showColNames = [], hideColNames = [];

    if (typeof(rows) === "undefined" || !$.isArray(rows) || rows.length === 0) {
        // something wrong need return
        return obj.page;
    }

    // find the index of the first dummy column
    // in the colModel. If we use rownumbers:true,
    // multiselect:true or subGrid:true additional
    // columns will be inserted at the begining
    // of the colModel
    iFirstDummy = -1;
    for(i=0;i<colModel.length;i++) {
        cmi = colModel[i];
        if (dummyTestRegex.test(cmi.name)) {
            iFirstDummy = i;
            break;
        }
    }
    if (iFirstDummy === -1) {
        // something wrong need return
        return obj.page;
    }

    orgShrinkToFit = clearShrinkToFit();

    // we get the first row of the JSON data
    firstRow = rows[0];
    for (prop in firstRow) {
        if (firstRow.hasOwnProperty(prop)) {
            // we will use the properties name of the first row
            // as the names of the column headers of the grid

            // find column index having prop as the name
            isFound = false;
            for(i=0;i<colModel.length;i++) {
                cmi = colModel[i];
                if (cmi.name === prop) {
                    isFound = true;
                    showColNames.push(prop);
                    break;
                }
            }
            if(!isFound) {
                // labels defines the column names
                cmi = colModel[iFirstDummy];
                showColNames.push(cmi.name);
                mygrid.jqGrid('setLabel',cmi.name,prop);

                // because of bug in jqGrid with calculation of width
                // we have to reset the width
                cmi.width = cmIntTemplate.width;

                // we set jsonmap which jqGrid will use instead
                // of dummy column names to read all row data
                cmi.jsonmap = prop;
                iFirstDummy++;
            }
        }
    }

    // fill the list of unused columns
    for(i=0;i<colModel.length;i++) {
        cmi = colModel[i];
        if ($.inArray(cmi.name, showColNames) === -1 && dummyTestRegex.test(cmi.name)) {
            hideColNames.push(cmi.name);
        }
    }
    mygrid.jqGrid('showCol',showColNames);
    mygrid.jqGrid('hideCol',hideColNames);

    setGridWidthAndRestoreShrinkToFit(orgShrinkToFit);

    return obj.page;
}

Внутри функции page я использую небольшие вспомогательные функции

var clearShrinkToFit = function() {
        // save the original value of shrinkToFit
        var orgShrinkToFit = mygrid.jqGrid('getGridParam','shrinkToFit');
        // set shrinkToFit:false to prevent shrinking
        // the grid columns after its showing or hiding
        mygrid.jqGrid('setGridParam',{shrinkToFit:false});
        return orgShrinkToFit;
    },
    setGridWidthAndRestoreShrinkToFit = function(orgShrinkToFit) {
        // calculate the new grid width
        var width=0, i=0, headers=mygrid[0].grid.headers, l=headers.length;
        for (;i<l; i++) {
            var th = headers[i].el;
            if (th.style.display !== "none") {
                width += $(th).outerWidth();
            }
        }

        // restore the original value of shrinkToFit
        mygrid.jqGrid('setGridParam',{shrinkToFit:orgShrinkToFit});

        // set the grid width
        mygrid.jqGrid('setGridWidth',width);
    },
    dummyTestRegex = new RegExp(dummyColumnNamePrefix+"(\\d)+");

Рабочую демонстрацию вы можетесм. здесь .

ОБНОВЛЕНО : Другой ответ с демо показывает, как создать сетку, которая имеет другой форматвходных данных: [[], [], ...] (массив массивов) - матрица.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...