0

In JQGrid table, one of the cells has a link in it, when clicked, it should execute a javascript.

{name : 'localAccountNo' , jsonmap : 'localAccountNo', label : 'Customer <br>Number', width:50, frozen:true, formatter : localAccountNumberCellFormatter}

JQGrid localAccountNumber cell formatter code

function localAccountNumberCellFormatter(cellvalue, options, rowObject)
{
    return '<a onclick="selectCustomer('+ rowObject +')">'+ cellvalue +'</a>';
}

Select customer javascript code

function selectCustomer(rowOfCustomer) {
    console.log(rowOfCustomer);
}

Clicking the link in the JQGrid cell failed with a syntax error.

Uncaught SyntaxError: Unexpected identifier

However when you pass the rowObject into selectCustomer method as string by escaping the object as depicted in the below code, it works. But it only pass the string representation of the object, not the actual object.

function localAccountNumberCellFormatter(cellvalue, options, rowObject)
{
    return '<a onclick="selectCustomer(\''+ rowObject +'\')">'+ cellvalue +'</a>';
}

The rowObject passed into selectCustomer method

enter image description here

G 1
  • 643
  • 7
  • 18
  • Which version of jqGrid you use and from which fork of jqGrid ([free jqGrid](https://github.com/free-jqgrid/jqGrid), commercial [Guriddo jqGrid JS]http://guriddo.net/?page_id=103334() or an old jqGrid in version <=4.7)? Which `datatype` you use? If your grid has local data, then you can use rowid to get the information about the row data. There are many ways to solve your problem, depend on the version and fork of jqGrid, which you use. You can use `formatter: "showlink"` , for example, in case of usage free jqGrid. – Oleg Jan 26 '17 at 06:41
  • I am using commercial jqGrid 4.8.2 (License: http://guriddo.net/?page_id=103334) Datatype is json and data is not local. As you have mentioned in your comment, I am using a custom formatter to achive this, but I cannot pass the rowObject to selectCustomer method as a parameter. – G 1 Jan 26 '17 at 07:07
  • I don't recommend you to use old Guriddo 4.8.2. You should either use the latest version of commercial fork: Guriddo jqGrid JS 5.2.0 or the latest version of free jqGrid: 4.13.6. I wrote my answer, which describes some alternatives to solve your problem. All the alternatives use only common features of jqGrid existing in all versions and all forks. I would recommend you additionally to define always [unformat](http://www.trirand.com/jqgridwiki/doku.php?id=wiki:custom_formatter#unformatting) if you defines custom `formatter`. – Oleg Jan 26 '17 at 09:25
  • Small comment: [event bubbling](https://en.wikipedia.org/wiki/Event_bubbling) is **not** the same as event binding. – Oleg Jan 26 '17 at 09:51
  • Sorry my lack of knowledge in events. Now I know what event bubbling is. Thank you very much. – G 1 Jan 26 '17 at 10:04
  • You are welcome! The usage of `.close` starting from `this` or `e.target` is the most quickly way to access the parent elements of the clicked cell. Setting of `onclick` attribute allocate more memory and require to use **global** functions. On the other side you can use `$("#gridis").click(function(e) { /*test e.target*/})` and register only one `click` event handler on the whole grid. The event handler should be not rebind on sorting/paging or any other reloading of *data* in the grid. Examples, which used `beforeSelectRow`/`onCellSelect` demonstrates this. – Oleg Jan 26 '17 at 10:09

3 Answers3

1

Custom formatter should be correct HTML fragment. Thus you have to encode the rowObject as string (using JSON.stringify, for example) and escape the quotes of the string inside of the custom formatter. The method selectCustomer will have to convert the string parameter back to object (using JSON.parse) before be able to use rowObject.

There are better alternative ways, which you can to use in the most cases. onclick handle will be start with DOM of <a> as this and event initialized to the Event object of the Click event. Thus you can, for example, use just

function localAccountNumberCellFormatter(cellvalue, options, rowObject) {
    return '<a onclick="selectCustomer.call(this)">'+ cellvalue +'</a>';
}

to get rowid from the parent row and to call getRowData using the rowid to get the data from other columns. You will get exactly the same like rowObject, but almost the same in the most cases:

function selectCustomer (event) {
    var $tr = $(this).closest(".jqgrow"), rowid = $tr.attr("id"),
        $grid = $tr.closest(".ui-jqgrid-btable"),
        item = $grid.jqGrid("getRowData", rowid);
    alert("item.lastName=" + item.lastName);
}

You can use

return '<a onclick="return selectCustomer.call(this, event);">'+ cellvalue +'</a>';

and return false from selectCustomer to prevent event bubbling. Forwarding of event object allows you to use event.target inside of the selectCustomer instead of this.

By the way, if you really need to use rowObject associated with the row, then it would be better to save it as data-somevalue attribute of the row (<tr>) element. See the old answer, which shows how to use rowattr to do this. You will can use $tr.data in the above code of selectCustomer to access the object.

If you remind about the event bubbling then it will be clear, that one don't need to set onclick attribute on every <a> element in the column. Instead of that you can just place <span> with CSS classes, which makes the text looking like link, thus the users understand that one can click on the text. One can register only one click handler on the <table> element, which will be called because of event bubbling. By the way jqGrid has already click handler. You can use beforeSelectRow or onCellSelect, which will be called inside of the click handler. The second parameter (e) of the callback is the Event and you can use e.target to access to the clicked <span>. You can find more details of the approach in the answer, in this one or some other.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Thank you for your answer. Your answer is very informative. This is how i did it, I added a new hidden column to the grid with a custom formatter, which stores the rowData obejct in a
    `function rowDataCellFormatter(cellvalue, options, rowObject) { var cellData = '
    '; return cellData; }` I passed the id data to selectCustomer method and retrieve the object as below. `function selectCustomer(rowOfCustomer) { var selectedCustomer = $('#'+rowOfCustomer+'div').data().dataobj; }`
    – G 1 Jan 26 '17 at 09:54
  • You are welcome! Why you need create **new column**? The `rowObject` are independent from a column. The data are the same for **the row**. The callback `rowattr`, which I referenced in my answer and [the old answer](http://stackoverflow.com/a/18313154/315935) shows how to set `data-dataObj` as the attribute of the `` element. You can get the data by rowid using `$('#'+rowid).data().dataobj`. The rowid can be accessed in custom formatter using `options.rowId`. – Oleg Jan 26 '17 at 10:04
  • Yes. You are correct. My solution is not clean. I have to update my code to use a custom row attribute to store rowData object as you have mentioned in your answer in the other post. I learned a lot from your answers about JQGrid and JS(Not only from this thread, but your other posts available in StackOverflow) Thank you for your help and support. – G 1 Jan 26 '17 at 10:18
  • You are welcome! Now you know some options and you can choose the way which better corresponds your requirements. Additional info: you don't wrote which version of jqGrid you use and from which fork of jqGrid. I recommend you to try [free jqGrid](https://github.com/free-jqgrid/jqGrid) from CDN for example (see [the wiki](https://github.com/free-jqgrid/jqGrid/wiki/Access-free-jqGrid-from-different-CDNs)). It's the fork, which I develop starting with end of 2014 (after making the main fork commercial and renaming it to Guriddo jqGrid). One can use it completely free of charge. – Oleg Jan 26 '17 at 10:23
  • I just forked your repository.I will look into that. You are a great help Oleg. Thank you. – G 1 Jan 26 '17 at 10:51
  • You are welcome! It's compatible to old jqGrid and you probably not require to use any changes in your code. On the other side it implements many other new features described in READMEs to every published version and someone in [the wiki](https://github.com/free-jqgrid/jqGrid/wiki). Some other options are simplified. I'd recommend you to look through [the article](https://free-jqgrid.github.io/getting-started/index.html) first of all. – Oleg Jan 26 '17 at 10:55
0

You can use JSON.stringify to pass the object

return '<a onclick="selectCustomer('+ JSON.stringify(rowObject) +')">'+ cellvalue +'</a>';
Mairaj Ahmad
  • 14,434
  • 2
  • 26
  • 40
0

If you don't have to support IE, you could use template strings:

function localAccountNumberCellFormatter(cellvalue, options, rowObject) {
    return `<a onclick="selectCustomer(${rowObject})">${cellvalue}</a>`;
}
apeltz
  • 71
  • 1
  • 5