2

In a custom button in my pager, I call grid.jqGrid("getGridParam", "data"), "data") to get all the data in the grid but it returns empty array. When I call grid.jqGrid("getGridParam", "data") in the loadComplete function, it still returns an empty array. However if I call grid.jqGrid('getRowData') it gives me the data I am looking for. See my code below.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
         pageEncoding="ISO-8859-1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <link rel="stylesheet" type="text/css" media="screen" href="${pageContext.request.contextPath}/css/jquery-ui.min.css"/>
    <link rel="stylesheet" type="text/css" media="screen" href="${pageContext.request.contextPath}/css/ui.jqgrid.css"/>
    <!--   Overide css styling to ensure that calendar image is inline with text box -->
    <style type="text/css">.ui-jqgrid .ui-search-table .ui-search-input > input,
                            .ui-jqgrid .ui-search-table .ui-search-input > select,
                            .ui-jqgrid .ui-search-table .ui-search-input > img {vertical-align: middle; display: inline-block;}
    </style>
    <script src="${pageContext.request.contextPath}/js/jquery-1.11.0.min.js" type="text/javascript"></script>
    <script src="${pageContext.request.contextPath}/js/jquery-ui.min.js" type="text/javascript"></script>
    <script src="${pageContext.request.contextPath}/js/grid.locale-en.js" type="text/javascript"></script>
    <script src="${pageContext.request.contextPath}/js/jquery.jqGrid.min.js" type="text/javascript"></script>
    <title>Trucks Overview</title>

    <script type="text/javascript">
    jQuery().ready(function () {
        var grid = jQuery("#truck_grid");
        var orderGridDialog = $('#truck_grid_dialog');  
        var gridData;

        getUniqueNames = function(columnName) {
            var texts = grid.jqGrid('getCol', columnName, false);
            var uniqueTexts = [], textsLength = texts.length, text, i, textsMap = {}; 
            for (i=0;i<textsLength;i++) {
                text = texts[i];
                if (text != undefined && textsMap[text] === undefined) {
                    // to test whether the texts is unique we place it in the map.
                    textsMap[text] = true;
                    uniqueTexts.push(text);
                }
            }
            return uniqueTexts;
        };
        buildSearchSelect = function(uniqueNames) {
            var values=":All";
            $.each (uniqueNames, function() {
                values += ";" + this + ":" + this;
            });
            return values;
        };
        setSearchSelect = function(columnName) {
            grid.jqGrid('setColProp', columnName,
                        {   stype: 'select',
                            searchoptions: {
                                value:buildSearchSelect(getUniqueNames(columnName)),
                                sopt:['eq']
                            }
                        }
            );
        };

        var initDateWithButton = function (elem) {
            if (/^\d+%$/.test(elem.style.width)) {
                // remove % from the searching toolbar
                elem.style.width = '';
            }
            // to be able to use 'showOn' option of datepicker in advance searching dialog
            // or in the editing we have to use setTimeout
            setTimeout(function () {
                $(elem).datepicker({
                    dateFormat: 'mm/dd/yy',
                    showOn: 'button',
                    changeYear: true,
                    changeMonth: true,     
                    buttonImageOnly: true,
                    buttonImage: "images/calendar.gif",
                    buttonText: "Select date",
                    showButtonPanel: true,
                    onSelect: function (dateText, inst) {
                        inst.input.focus();
                        if (typeof (inst.id) === "string" && inst.id.substr(0, 3) === "gs_") {
                             $(inst.id).val(dateText);
                             grid[0].triggerToolbar();
                        }
                        else {
                            // to refresh the filter
                            $(inst).trigger("change");
                        }
                    }
                });
            }, 100);
        };

        grid.jqGrid({
            url: '${pageContext.request.contextPath}/getTrucksJSONAction',
            datatype: "json",
            mtype: 'GET',
            colNames: ['Truck ID', 'Status', 'Carrier Code', 'Date Created', 'Date Closed', 'T1 Status', 'Truck Arrived'],
            colModel: [
                {name: 'truckId', key:true, index: 'truckId', align: 'center', width: 100},
                {name: 'status', index: 'status', align: 'center', width: 100},
                {name: 'carrierName', index: 'carrierName', align: 'center', width: 100},
                {name: 'createdDate', index: 'createdDate', align: 'center', width: 100},
                {name: 'closedDate',  index: 'closedDate', align: 'center', width: 100},
                {name: 't1Status', sortable: false, align: 'center', width: 100, fixed: true,
                    formatter: function (celvalue) {
                        return celvalue ?
                            "<img src='http://www.clker.com/cliparts/q/j/I/0/8/d/green-circle-icon-md.png' alt='green light' style='width:15px;height:15px'/>" :
                            "<img src='http://www.iconsdb.com/icons/preview/red/circle-xxl.png' alt='red light' style='width:10px;height:10px'/>";
                    }} ,
                {name: 'truckArrived', sortable: false, align: 'center', width: 100, fixed: true,
                        formatter: function (celvalue) {
                            return celvalue ?
                                "<img src='http://www.clker.com/cliparts/q/j/I/0/8/d/green-circle-icon-md.png' alt='green light' style='width:15px;height:15px'/>" :
                                "<img src='http://www.iconsdb.com/icons/preview/red/circle-xxl.png' alt='red light' style='width:10px;height:10px'/>";
                        }}    
            ],
            rowNum: 10,
            height: 300,
            autoheight: true,
            autowidth: true,
            rowList: [10, 20, 30],
            pager: jQuery('#truck_grid_pager'),
            sortname: 'truckId',
            sortorder: "desc",
            jsonReader: {
                root: "records",
                page: "page",
                total: "total",
                records: "rows",
                repeatitems: false
            },
            viewrecords: true,
            altRows: false,
            gridview: true,
            hidegrid: false,
            multiselect:true,
            recordtext: '',
            emptyrecords: 'No Trucks',
            forceFit: true,
            caption: "Trucks Overview",
            loadComplete: function() { 
                // Reload the grid after changing paginattion
                var allRecords = grid.getGridParam('lastpage') * grid.getGridParam('records');
                grid.jqGrid('setGridParam', { 
                    recordtext: allRecords + ' Trucks(s) Found. Displaying {0} to {1}'});   
                $(this).trigger("reloadGrid");
                async: false,
                setSearchSelect('status');
                setSearchSelect('carrierName');
                grid.jqGrid('setColProp', 'truckId', {
                    searchoptions : {
                        sopt : [ 'bw' ],
                        dataInit : function(elem) {
                           $(elem).autocomplete({
                              source : getUniqueNames('truckId'),
                              delay : 0,
                              minLength : 0
                           });
                       }
                    }
                });   
                grid.jqGrid('setColProp', 'createdDate', {
                    sorttype: 'date', editable: true,
                        editoptions: { dataInit: initDateWithButton, size: 8 },
                        searchoptions: {
                            sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge'],
                            dataInit: initDateWithButton
                        }
                });   
                gridData = $(this).jqGrid("getGridParam", "data");
                grid.jqGrid('filterToolbar', {autoSearch: true});
            },
        }).navGrid('#truck_grid_pager', {edit: false, add: false, del: false, search: false, refresh: true})
        .navButtonAdd('#truck_grid_pager', {caption:"Truck Arrived", buttonicon:"ui-icon-flag",  position:"first", title:"Truck Arrived",
            onClickButton: function(){ 
                var i;
                var data = grid.jqGrid("getGridParam", "data");
                var selRowIds = grid.jqGrid('getGridParam', 'selarrrow');
                for (i = 0; i < data.length; i++) {
                    if (selRowIds.indexOf(data[i].truckId) > -1) {
                        data[i].truckArrived = true;
                    }
                }
                grid.trigger("reloadGrid");
             }
        })
        .navButtonAdd('#truck_grid_pager', {caption:"Ship Confirm", buttonicon:"ui-icon-circle-check",  position:"first", title:"Ship Confirm",
            onClickButton: function(){ 
             alert("Ship has been confirmed");}
        });

        orderGridDialog.dialog({
            autoOpen: false,
            width: 1000,
            height: 400,
            draggable: false,
            show: {
                effect: "blind",
                duration: 500
            },
            hide: {
                effect: "blind",
                duration: 250
            },
            close: function(event, ui){
                orderGridDialog.text('Loading Grid...');
            }
        });
    });

</script>
</head>
<body>
<table id="truck_grid"></table>
<div id="truck_grid_pager"></div>
<div id="truck_grid_dialog" title="Orders Overview">Loading...</div>
</body>
</html>


The problem happens in the last section of the code, namely:

        .navButtonAdd('#truck_grid_pager', {caption:"Truck Arrived", buttonicon:"ui-icon-flag",  position:"first", title:"Truck Arrived",
            onClickButton: function(){ 
                var i;
                var data = grid.jqGrid("getGridParam", "data");
                var selRowIds = grid.jqGrid('getGridParam', 'selarrrow');
                for (i = 0; i < data.length; i++) {
                    if (selRowIds.indexOf(data[i].truckId) > -1) {
                        data[i].truckArrived = true;
                    }
                }
                grid.trigger("reloadGrid");
             }
        })

The second problem I have is when grid.trigger("reloadGrid") is called, the truckArrived icon is not changed from red to green as expected.

pomeh
  • 4,742
  • 4
  • 23
  • 44
Terry
  • 43
  • 1
  • 3
  • 10

1 Answers1

3

The internal parameter data will be used only if one uses datatype: "local". You use datatype: "json". It means that the server hold whole dataset only. The url: '${pageContext.request.contextPath}/getTrucksJSONAction' receive request for the page of sorted and filtered data. The server should implement sorting, filtering/sorting and paging.

There exists a special case: one use remote datatype ("json" or "xml"), but one uses loadonce: true parameter additionally. In the case the server should return all unfiltered data instead of providing the page of data. The returned data should be still sorted corresponds to sortname, sortorder parameter (which will be sent to the server as sidx and sord). jqGrid displays the first page of returned data, but it fills the internal data parameter with whole rows of data returned from the server. After the first loading of data jqGrid changes datatype to "local" and so the later sorting, paging and filtering of data will be like in case of datatype: "local". In the case yoou will be able to get all the data using grid.jqGrid("getGridParam", "data"), but you can do this of case after the data will be once loaded.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • thanks for your answer. How can ensure that my server returns unfiltered data instead of a url/page of data – Terry Sep 12 '14 at 11:50
  • 1
    In this project, we don't want to use loadonce option because the dataset changes frequently in the database. So let us forget about the loadonce and data options. If I replacegrid.jqGrid("getGridParam", "data"); with If I replace var data = grid.jqGrid("getRowData"); I get the correctly filled array of grid data. But the problem is when grid.trigger("reloadGrid") is called, the truckArrived icon is not changed from red to green as expected. How can I solve this problem? – Terry Sep 12 '14 at 13:10
  • @Terry: Sorry, but I don't understand your question. *You should write the code of both the server and the client* and the client code should corresponds to the server. So you should first analyse the requirements of your project and choose the best way. – Oleg Sep 12 '14 at 13:10
  • @Terry: If the server don't return *full data* to the client and jqGrid hold only **the current page of data** then one can't get **all the data** on the client side (by any jqGrid API). – Oleg Sep 12 '14 at 13:12
  • If I replace grid.jqGrid("getGridParam", "data"); with data = grid.jqGrid("getRowData"); I get the full grid data. But the problem is when grid.trigger("reloadGrid") is called, the truckArrived icon is not changed from red to green as expected. How can I solve this problem? – Terry Sep 12 '14 at 13:14
  • @Terry: You used `datatype: "local"` in your previous questions where one changed `icon` dynamically. `reloadGrid` worked **locally**, one used `data[i].truckArrived = true;` with **local** `data`. In other words *all the code was oriented to the working with local data*. You have to change all the parts of code **to post the data to the server** and reduce reloading to the minimum. – Oleg Sep 12 '14 at 13:17
  • @Terry: You should understand that jqGrid contains **many alternative parts of code**. So it's extremely important to decide the strategy depend on your project requirements. The most important things are 1) choosing of `datatype` 2) choosing of `loadonce` 3) choosing of editing mode (form editing, inline editing, cell editing) 4) choosing of implementation way of the editing. I mean under the last part for example whether to use `editRow` directly of use `inlineNav` or use `formatter: "actions"`. If you try to change the above choices you could need to **rewrite** your server code/client code – Oleg Sep 12 '14 at 13:24
  • Sorry for bothering you. I really appreciate your help. The code with datatype: **"local"** is the work I do at home as a hobby/tutorial. It contained a list of Countries and data[i].Developed = true. The code I posted in this question is my official Company project about trucks where data[i].truckArrived = true and datatype=json. So I want to keep datatype=json for this code. So my question how can I ensure that when grid.trigger("reloadGrid") is called, the truckArrived icon is changed from red to green as expected? – Terry Sep 12 '14 at 14:21
  • @Terry: You should rewrite the most parts of your code. `getUniqueNames` get names from **the current page** only and so one will be not able to find the data which are not yet on the page. I suppose that the usage of `getUniqueNames` is wrong way for pure server based data. The code of `"Truck Arrived"` button have to be rewritten too. You can send the array of selected items `grid.jqGrid('getGridParam', 'selarrrow');` **to the server**, the server should change `truckArrived` properties of the items on the server. The next `reloadGrid` will refresh the grid. – Oleg Sep 12 '14 at 14:47
  • You are right about the getUniqueNames code, it only works properly only on the first page. What I mean is, it shows a drop down box of values contained only on the first page. I wish I knew how to rewrite the code for getUniqueNames and "Truck Arrived" button. This is the first time that I use jqgrid in a project. Could you please give me some help with the code for these 2 functions? – Terry Sep 12 '14 at 14:58
  • @Terry: You can use `SELECT DISTINCT carrierName` and `SELECT DISTINCT status` and include the results to the data returned from the main URL (`getTrucksJSONAction`). Inside of `beforeProcessing` you can set `searchoptions.value`. See [the answer](http://stackoverflow.com/a/17410568/315935) or [the answer](http://stackoverflow.com/a/19427444/315935). – Oleg Sep 12 '14 at 15:46
  • Many thanks Oleg. This solution is more suitable to my server based data. I will try it on monday. For the "Truck Arrived button" can I used the solution you wrote in the following url: http://stackoverflow.com/questions/3816874/jqgrid-howto-send-all-rowdata-in-json-format-to-server/3817174#3817174 and also this one: http://stackoverflow.com/questions/3587480/jquery-modal-dialog-and-jqgrid/3588732#3588732 – Terry Sep 12 '14 at 20:59
  • @Terry: You are welcome! Both answers contains the main part which you can use. In general your case could be even more simple. You can just get the array of selected ids: `var ids = grid.jqGrid("getGridParam", "selarrrow");`, make comma separated string of ids: `var strIds = ids.join(",");` and then just send `strIds` to the server: `$.ajax({type: "POST", url: "yourSrvUrl", data: { ids: strIds }});`. – Oleg Sep 12 '14 at 21:11
  • You are simply amazing, you deserve an award for JQuery and Javascript. Please I have one last question: could you help me solve the issue I described the following url: http://stackoverflow.com/questions/25768231/datepicker-reads-month-as-date-in-dd-mm-yy-format. The server sends a date string in the dd/mm/yy format and the grid correctly displays it in that format but when the user selects a date via the datepicker, it is shown in the datepicker text in the mm/dd/yy format. If a user types a date in the search text box and presses ENTER, the date is interpreted in the mm/dd/yy format – Terry Sep 12 '14 at 21:35
  • @Terry: On need the demo which reproduces the problem. The question don't contains the column definition (whether `formatter: "date"` be used or not and all other options). In general I don't recommend ever to send date over the wire in some locale format. I recommend to use ISO 8601 format: `2014-09-13`. It's default input format which jqGrid uses. – Oleg Sep 12 '14 at 22:07
  • The column definition is the same as the createdDate in the question on this page. I do the formatting in the loadComplete: function(). We want to use either the 13/09/2014 or the 13-09-2014 format. Are there standard ISO formats for these date formats?? – Terry Sep 13 '14 at 07:32
  • @Terry: Sorry, but I see lees sense in what you do. Why you set properties of `'createdDate'` in `loadComplete`? It means that you fill initial grid using one set of properties and then set in `loadComplete`? Why you don't use `formatter: "data"` and just use `sorttype: 'date'`? **I think that you should use `formatter: "date"` with corresponding `formatoptions` opetions**. Moreover you should post the questions so that every new reader could quickly understand it and compare with his problem. You can't post important parts of descriptions of the question in comments to another question. – Oleg Sep 13 '14 at 08:26