LCJ
LCJ

Reputation: 22652

Updating value in jqGrid doesn't work when two columns use same field

I used the solution mentioned in How to update value of data in jqgrid to update data locally. It worked for me as shown in the first fiddle. In the "Action" column, there is button added conditionally, based on the data in "IsActive" column. If it is "true", a "Retire" button gets added as an action. If it is false, "Activate" button gets added. When the javascript function is called, the button changes to "Activate".

Fiddle 1

Now, I added another column to display the status value as text. Now, both "Status" column and "Action" column are utilizing the same data column - IsActive. After adding this column, the javascript function is not changing the button from "Retire" to "Activate".

Fiddle 2

What is the best way to fix this issue?

CODE

$(document).ready(function () {

function updateActiveStatus(rowid, isToActive) {

alert('function');

                        // first change the cell in the visible part of grid
                        $("#list").jqGrid('setCell', rowid, 'firstname', 'A');

                        // now change the internal local data
                        $("#list").jqGrid('getLocalRow', rowid).firstname = 'A';


                        $("#list").jqGrid('setCell', rowid, 'IsActive', false);
                        $("#list").jqGrid('getLocalRow', rowid).IsActive = false;



            }


            var myData = [

                { "id": "35", "firstname": null, "codeval": "G", "note": "xx7866", "amount": "23", "IsActive": true },
                { "id": "73", "firstname": null, "codeval": "W", "note": "dd1047", "amount": "34", "IsActive": true },
                { "id": "75", "firstname": "LORA", "codeval": "H", "note": "rr7323", "amount": "56", "IsActive": true },
                { "id": "95", "firstname": "EST", "codeval": "M", "note": "gg574", "amount": "55", "IsActive": true }
                ],

                myGrid = $("#list");

            myGrid.jqGrid({
                datatype:'local',
                data: myData,
                colNames: ['ID', 'FirstName', 'Code', 'Amount', 'Note', 'Action'],
                colModel:[
                    {name:'id',width:70,align:'center',sorttype: 'int'},
                    {name:'firstname',width:80, align:'center'},
                    { name: 'codeval',  width: 70 },
                    {name:'amount',width:100, formatter:'number'},
                    {name:'note',index:'note',width:100,sortable:false},
                     {
                        name: 'IsActive',
                        width: 100,
                        formatter: function (cellvalue, options, rowObject)                                                 {
                            if (cellvalue == true) {
                                return '<div style="padding-left:5px;"><button class="ui-button ui-widget ui-state-default app-custom-button-retire" >' +
                                        '<span title="" class="ui-button-icon-primary ui-icon ui-icon-scissors"></span>Retire' +
                                        '</button></div>';
                            }
                            else {
                                return '<div style="padding-left:5px;"><button class="ui-button ui-widget ui-state-default app-custom-button-activate" >' +
                                        '<span title="" class="ui-button-icon-primary ui-icon ui-icon-check"></span>Activate' +
                                        '</button></div>';
                            }
                        }
                    }
                ],
                rowNum:10,
                pager: '#pager',
                gridview:true,
                ignoreCase:true,
                rownumbers:true,
                viewrecords: true,
                sortorder: 'desc',
                height: '100%',
                beforeSelectRow: function (rowid, e) {
                    var $self = $(this),
                        $td = $(e.target).closest("tr.jqgrow>td"),
                        rowid = $td.parent().attr("id"),
                        //rowData = $self.jqGrid("getLocalRow", rowid),
                        rowData = $self.jqGrid("getRowData", rowid)
                    iCol = $td.length > 0 ? $td[0].cellIndex : -1,
                    colModel = $self.jqGrid("getGridParam", "colModel");

                    celValue = $self.jqGrid('getCell', rowid, 'FirstName');

                    if (iCol >= 0 && colModel[iCol].name === "IsActive") {

                        if ($(e.target).hasClass("app-custom-button-retire")) {
                            updateActiveStatus(rowid,false);
                            return false;
                        }

                        if ($(e.target).hasClass("app-custom-button-activate")) {

                            updateActiveStatus(rowid, true);
                            return false;
                        }
                    }


                    //Avoid selection of row
                    return false;
                }
            });
            myGrid.jqGrid('filterToolbar', { stringResult: true, searchOnEnter: false, defaultSearch: "cn" });

        });

Upvotes: 0

Views: 740

Answers (1)

Oleg
Oleg

Reputation: 221997

I seem multiple misunderstanding in your code. First of all you have some source data, which are the array of item. Every item is object with multiple properties, like:

{ "id": "75", "firstname": "LORA", "codeval": "H", "note": "rr7323",
  "amount": "56", "IsActive": true }

or, which is the same,

{ id: "75", firstname: "LORA", codeval: "H", note: "rr7323",
  amount: "56", IsActive: true }

It should be clear that such item can't have multiple properties with the same name. The object

{ "id": "75", "firstname": "LORA", "codeval": "H", "note": "rr7323",
  "amount": "56", "IsActive": true, "IsActive": true }

would be wrong even if some web browser could ignore the error. Even if you specify the same value true for both "IsActive" properties.

In the same way you can't use colModel with multiple columns with the same name property. Your second demo https://jsfiddle.net/LijoCheeran/rqab1veh/11/ have two columns with the same property name: 'IsActive'. It's wrong. You can fix the code by usage, for example, name: 'IsActive1' in the second column. The formatter of IsActive1 can use rowObject.IsActive instead of cellvalue to access to the required data. The corresponding code will be the follwing

{
    name: 'IsActive1',
    width: 75,
    formatter: function (cellvalue, options, rowObject) {
        return rowObject.IsActive == true ? 'Active' : 'Retired';
    }
},
{
    name: 'IsActive',
    width: 100,
    formatter: function (cellvalue, options, rowObject) {
        return cellvalue == true ? retireButton : activeButton;
    }
}

where retireButton and activeButton contains HTML fragments of the buttons.

Now it's important to understand, that jqGrid hold the data array. The method $("#list").jqGrid('getLocalRow', rowid) get you the reference to the data item which corresponds the data of the row. The method getRowData will get the data from HTML representation of the cells (from <td> elements) and unformat there. The type of the fields of returned object will be strings.

Because you need to update not only the data, but the cell content of firstname, IsActive1 and IsActive columns then you have to call setCell on every the field or better call one setRowData:

function updateActiveStatus (rowid, isToActive) {
    alert('calling the function');
    $("#list").jqGrid('setRowData', rowid, {
        firstname: 'A',
        IsActive1: false,
        IsActive: false
    });
    var item = $("#list").jqGrid('getLocalRow', rowid);
    // delete unneeded IsActive1 property created in the item
    delete item.IsActive1;
}

The only small disadvantage of the setRowData call is creating new property IsActive1 in the item of data. Old jqGrid 4.6 have no possibility to save the data "virtually" in some another place as the item.IsActive1. Free jqGrid allows to specify saveLocally callback, which can make custom "saving" of the data of the column in the local item. It's not real large problem in your case and you need just delete unneeded property by delete item.IsActive1

You can see the results on the modified demo https://jsfiddle.net/OlegKi/rqab1veh/12/

Upvotes: 1

Related Questions