32

I'm using the method addJsonRows to add local data to a jQgrid. As this method disables the sorting I need another solution. One restriction: I can't set the url and fetch the data from the server because the data was passed through another component.

Underneath snippet enlightens the case. The commented line shows the restriction, I replaced it by defining a local variable to have a test case.

<script type="text/javascript" language="javascript">
    function loadPackageGrid() {
    // Get package grid data from hidden input.
    // var data = eval("("+$("#qsmId").find(".qsm-data-packages").first().val()+")");
        var data =  {
            "page": "1",
            "records": "2",
            "rows": [
                { "id": "83123a", "PackageCode": "83123a" },
                { "id": "83566a", "PackageCode": "83566a" }
            ]
        };

        $("#packages")[0].addJSONData(data);
    };

    $(document).ready(function() {
        $("#packages").jqGrid({
            colModel: [
                { name: 'PackageCode', index: 'PackageCode', width: "110" },
                { name: 'Name', index: 'Name', width: "300" }
            ],
            pager: $('#packagePager'),
            datatype: "local",
            rowNum: 10000,
            viewrecords: true,
            caption: "Packages",
            height: 150,
            pgbuttons: false,
            loadonce: true
        });
    });
</script>

I wonder how I could do this in an other (better) way to keep the sorting feature. I tried something with the data option, without result.

Oleg
  • 220,925
  • 34
  • 403
  • 798
Brecht
  • 355
  • 2
  • 4
  • 7

2 Answers2

45

I suppose that the same question is interesting for other persons. So +1 from me for the question.

You can solve the problem in at least two ways. The first one you can use datatype: "jsonstring" and datastr: data. In the case you need to add additional parameter jsonReader: { repeatitems: false }.

The second way is to use datatype: "local" and data: data.rows. In the case the localReader will be used to read the data from the data.rows array. The default localReader can read the data.

The corresponding demos are here and here.

I modified a little your data: filled "Name" column and included the third item in the input data.

Now you can use local paging, sorting and filtering/searching of the data. I included a little more code to demonstrate the features. Below you find the code of one from the demos:

$(document).ready(function () {
    'use strict';
    var data = {
            "page": "1",
            "records": "3",
            "rows": [
                { "id": "83123a", Name: "Name 1", "PackageCode": "83123a" },
                { "id": "83432a", Name: "Name 3", "PackageCode": "83432a" },
                { "id": "83566a", Name: "Name 2", "PackageCode": "83566a" }
            ]
        },
        grid = $("#packages");

    grid.jqGrid({
        colModel: [
            { name: 'PackageCode', index: 'PackageCode', width: "110" },
            { name: 'Name', index: 'Name', width: "300" }
        ],
        pager: '#packagePager',
        datatype: "jsonstring",
        datastr: data,
        jsonReader: { repeatitems: false },
        rowNum: 2,
        viewrecords: true,
        caption: "Packages",
        height: "auto",
        ignoreCase: true
    });
    grid.jqGrid('navGrid', '#packagePager',
        { add: false, edit: false, del: false }, {}, {}, {},
        { multipleSearch: true, multipleGroup: true });
    grid.jqGrid('filterToolbar', { defaultSearch: 'cn', stringResult: true });
});

UPDATED: I decided to add more details about the differences between datatype: "jsonstring" and datatype: "local" scenarios because the old answer be read and voted by many readers.

I suggest to modify the above code a little to show better the differences. The fist code uses datatype: "jsonstring"

$(function () {
    "use strict";
    var data = [
            { id: "10", Name: "Name 1", PackageCode: "83123a", other: "x", subobject: { x: "a", y: "b", z: [1, 2, 3]} },
            { id: "20", Name: "Name 3", PackageCode: "83432a", other: "y", subobject: { x: "c", y: "d", z: [4, 5, 6]} },
            { id: "30", Name: "Name 2", PackageCode: "83566a", other: "z", subobject: { x: "e", y: "f", z: [7, 8, 9]} }
        ],
        $grid = $("#packages");

    $grid.jqGrid({
        data: data,
        datatype: "local",
        colModel: [
            { name: "PackageCode", width: 110 },
            { name: "Name", width: 300 }
        ],
        pager: "#packagePager",
        rowNum: 2,
        rowList: [1, 2, 10],
        viewrecords: true,
        rownumbers: true,
        caption: "Packages",
        height: "auto",
        sortname: "Name",
        autoencode: true,
        gridview: true,
        ignoreCase: true,
        onSelectRow: function (rowid) {
            var rowData = $(this).jqGrid("getLocalRow", rowid), str = "", p;
            for (p in rowData) {
                if (rowData.hasOwnProperty(p)) {
                    str += "propery \"" + p + "\" + have the value \"" + rowData[p] + "\n";
                }
            }
            alert("all properties of selected row having id=\"" + rowid + "\":\n\n" + str);
        }
    });
    $grid.jqGrid("navGrid", "#packagePager",
        { add: false, edit: false, del: false }, {}, {}, {},
        { multipleSearch: true, multipleGroup: true });
    $grid.jqGrid("filterToolbar", { defaultSearch: "cn", stringResult: true });
});

It displays (see the demo)

enter image description here

One can see unsorted items in the same order like input data. The items of input data will be saved in internal parameters data and _index. getLocalRow method used in onSelectRow shows that items of internal data contains only properties of input items which names corresponds to name property of some jqGrid columns. Additionally unneeded _id_ property will be added.

On the other side the next demo which uses datatype: "local" displays sorted data and all properties inclusive complex objects will be still saved in the internal data:

enter image description here

The code used in the last demo is included below:

$(function () {
    "use strict";
    var data = [
            { id: "10", Name: "Name 1", PackageCode: "83123a", other: "x", subobject: { x: "a", y: "b", z: [1, 2, 3]} },
            { id: "20", Name: "Name 3", PackageCode: "83432a", other: "y", subobject: { x: "c", y: "d", z: [4, 5, 6]} },
            { id: "30", Name: "Name 2", PackageCode: "83566a", other: "z", subobject: { x: "e", y: "f", z: [7, 8, 9]} }
        ],
        $grid = $("#packages");

    $grid.jqGrid({
        data: data,
        datatype: "local",
        colModel: [
            { name: "PackageCode", width: 110 },
            { name: "Name", width: 300 }
        ],
        pager: "#packagePager",
        rowNum: 2,
        rowList: [1, 2, 10],
        viewrecords: true,
        rownumbers: true,
        caption: "Packages",
        height: "auto",
        sortname: "Name",
        autoencode: true,
        gridview: true,
        ignoreCase: true,
        onSelectRow: function (rowid) {
            var rowData = $(this).jqGrid("getLocalRow", rowid), str = "", p;
            for (p in rowData) {
                if (rowData.hasOwnProperty(p)) {
                    str += "propery \"" + p + "\" + have the value \"" + rowData[p] + "\"\n";
                }
            }
            alert("all properties of selected row having id=\"" + rowid + "\":\n\n" + str);
        }
    });
    $grid.jqGrid("navGrid", "#packagePager",
        { add: false, edit: false, del: false }, {}, {}, {},
        { multipleSearch: true, multipleGroup: true });
    $grid.jqGrid("filterToolbar", { defaultSearch: "cn", stringResult: true });
});

So I would recommend to use datatype: "local" instead of datatype: "jsonstring". datatype: "jsonstring" could have some advantages only in some very specific scenarios.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Once again big thanks for the answer! I notice that the demolinks are identical. However I managed it without the second demo, maybe it's useful for someone else. – Brecht Jul 26 '11 at 20:57
  • owesome answer, thanx to @Brecht for nice question. – sanghavi7 Nov 08 '12 at 07:05
  • hi, @Oleg, I have one problem in that I am retrieving data through json and adding to jqgrid. but want to search locally, is it possible? – sanghavi7 Nov 08 '12 at 07:12
  • @ankit5607san: I am not sure why you need the behavior. If I understand your problem correctly you can use `datatype: "json"` with `loadonce: true`. In the case you need load *all data* from the server at once and the `datatype` will be changed to `"local"` after the first loading from the server. All next paging ans sorting/filtering will be done locally. To be able to refresh the data in the grid you can reset the `datatype` inside if `beforeRefresh`: see [here](http://stackoverflow.com/a/3772720/315935). – Oleg Nov 08 '12 at 07:33
  • @Oleg here we are having an alert on clicking a row. Can we have another jqgrid on top of it? – shv22 Nov 08 '16 at 05:44
  • @shv22: Yes of cause. You can create Dialog (or div with position:absolute) with new grid or create Grid as Subgrid for example (see [here](http://www.trirand.com/jqgridwiki/doku.php?id=wiki:subgrid_as_grid) or [here](http://stackoverflow.com/a/10178440/315935)). – Oleg Nov 08 '16 at 05:49
  • @Oleg thank you for your quick response. So, I have to add another grid in onSelectRow of the first grid? – shv22 Nov 08 '16 at 06:07
  • @shv22: You don't describe exactly which kind of information you need to display. Thus it's difficult to answer you on the question where you use "I have to". You *can use* grid as subgrid, which seems to me the best choice based on information, which you currently post. There are other options too (TreeGrid, data grouping and so on). In case of Subgrid jqGrid create the column with a button ("+" by default). If the user click on the button, the row under the clicked row will be created and `subGridRowExpanded` be callked. You are free to display *any information* in the row inclusive a grid. – Oleg Nov 08 '16 at 06:29
  • @shv22: See pictures created for [the answer](http://stackoverflow.com/a/31567652/315935), [the demo](http://www.ok-soft-gmbh.com/jqGrid/SubGrid.htm), created for [the old answer](http://stackoverflow.com/a/4115481/315935), [the demo](https://jsfiddle.net/OlegKi/615qovew/64/), created for [the answer](http://stackoverflow.com/a/39546742/315935) – Oleg Nov 08 '16 at 06:35
  • @Oleg sorry for not being clear on my question. I want a tree jqGrid which on clicking on + will have another jqgrid like a modal window we have in this question http://stackoverflow.com/questions/36342432/display-bootstrap-modal-dialog-on-top-of-child-popup-window just the difference is there window but I want table – shv22 Nov 08 '16 at 06:44
  • @shv22: I repeat that you should *describe an example of the data, which you need to display*. Your last comment means, that *you shouldn't use TreeGrid*. The usage of TreeGrid means that you have hierarchy of items and all the child items have **the same properties** as the parent node (see carefully on the *columns* of every row of the TreeGrid [here](http://stackoverflow.com/a/5333199/315935) for example). – Oleg Nov 08 '16 at 07:29
  • @Oleg, I have posted my question here...please look into it http://stackoverflow.com/questions/40481585/jqgrid-as-a-modal-window-on-top-of-another-jqgrid – shv22 Nov 08 '16 at 07:52
  • @shv22: I still don't full understand what you want to do and why. I repeat that it would be better if you *more detailed describe the input data*, which you have and describe *why* you want to display modal dialog. The first look on the data from your question looks like you should better use 3-level data grouping with `"header"` as `groupSummaryPos` (see [here](http://www.ok-soft-gmbh.com/jqGrid/OK/grouping2-summaryTypeAsArray.htm)) or `jqPivot` (see [here](http://www.ok-soft-gmbh.com/jqGrid/OK/pivotGroupingTotalsHideSomeColumns.htm)). One should first choose the best way to display the data – Oleg Nov 08 '16 at 08:21
  • @Oleg this is what it is needed in our project....we already have 3 level grouping on our base grid now the demand is to have another jqgrid on top of it as an another modal window which will appear by clicking on the root node – shv22 Nov 08 '16 at 09:02
  • @shv22: It's unclear many details: Which `datatype` you have? Where you have the data, which you need to display in the new grid? Which version of jqGrid you use (can use) and from which fork of jqGrid. Moreover I still not understand where you have some Implementation problems. Do you use jQuery UI or Bootstrap? Do you have static or dynamic div, which you use for the Dialog? Has the dialog ein ``? Why you not just call `.jqGrid` on the table during opening the dialog? Where you have some problems?
    – Oleg Nov 08 '16 at 09:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/127608/discussion-between-shv22-and-oleg). – shv22 Nov 08 '16 at 09:15
-1

Great advice, Oleg.

In my web app, I pre-loaded some JSON data which looked like this:

    {
       WorkflowRuns: 
       [
           {
              WorkflowRunID: 1000,
              WorkflowRunName: "First record",
           },
           {
              WorkflowRunID: 1001,
              WorkflowRunName: "Second record",
           }
       ],
       UserInformation: 
       {
          Forename: "Mike",
          Surname: "Gledhill"
       }
}

And here's the code I needed to create the jqGrid, just based on the WorkflowRuns part of this JSON:

var JSONstring = '{ WorkflowRuns: [ { WorkflowRunID: 1000, .. etc .. } ]';

$("#tblWorkflowRuns").jqGrid({
    datatype: "local",
    data: JSONstring.WorkflowRuns,
    localReader: {  
        id: "WorkflowRunID",
        repeatitems: false
    },
    ...
});

This was a bit of trial and error though.

For example, jqGrid seemed to ignore datastr: JSONstring for me.

And notice how, with local data, I needed to use localReader, rather than jsonReader, otherwise it wouldn't set the row IDs properly.

Hope this helps.

Mike Gledhill
  • 27,846
  • 7
  • 149
  • 159