1

I am using jqGrid and want to know the best solution to implement it. I am using backbone and jQuery. Following are the feature required

  1. Columns with Hyperlink. It will be Edit/Delete/Custom hyperlinks.
  2. On click on link, basically it should not navigate just call some function. For example, on delete it will just delete the row.
  3. Number of hyperlink columns are dynamic.

Hyperlink can be done in two ways

1) Use showlink formatter or Customer formatter. Problem with showlink is we can call only global functions and i am not comfortable writing my click event logic in loadComplete function. Because my grid is re-usable and dont know the number of columns i will be having hyperlink. So i am using custom formatter like this

deleteLinkFmatter : function(cellvalue, options, rowObject)
{
   return '<a onclick="deleteRow(' + options.rowId + ')">'+ cellvalue + '</a>';
}

Problem with the above code is, in backbone.js its saying that deleteRow not found. I found different ways suggested in this site but all in vain. Can any one suggest a solution?

Oleg
  • 220,925
  • 34
  • 403
  • 798
Kishan
  • 71
  • 3
  • 8

1 Answers1

3

I agree that the predefined formatter showlink is oriented on hyperlink and it's not comfortable in case when you need to start your custom JavaScript function on click on the link. Nevertheless in the answer you would find the code which explain how you can use showlink in the case.

If you want to add Edit/Delete/Custom hyperlinks in separate columns you can easy use dynamicLink which I wrote and described here. You are right, if you write that the function which you call in onclick attribute of <a> must be defined on the global level. You should not forget, that one can use some common global namespace like jQuery and define many functions which can be called from the jQuerynamespace. For example dynamicLink which you can download from here can be used in the same way as showlink. For example

{ name: 'editlink', formatter: 'dynamicLink',
    formatoptions: {
        onClick: function (rowid, iRow, iCol, cellText, e) {
            // any your code
        }
    }}

In the implementation the method $.fn.fmatter.dynamicLink.onClick from the dynamicLink will be used in the onclick attribute.

If you prefer to use unobtrusive JavaScript style I would recommend you to read the following answers: this, this and this with the corresponding demos this, this and this. Alternatively you can use doInEachRow which simplify a little the enumeration

loadComplete: function() {
    var iCol = getColumnIndexByName.call(this, 'editlink'); // get index of the column

    $(this).jqGrid('doInEachRow', function (row, rowId, localRowData) {
        $(row.cells[iCol]).children("a").click(function (e) {
            e.preventDefault();
            // any your code here
        });
    });
}

where

var getColumnIndexByName = function (columnName) {
        var $this = $(this), cm = $this.jqGrid('getGridParam', 'colModel'), i,
            l = cm.length;

        for (i = 0; i < l; i++) {
            if (cm[i].name === columnName) {
                return i; // return the index
            }
        }
        return -1;
    };

You can easy modify the above code for the case if you place many <a> hyperlinks in one column. In the case you can just replace .children("a") part of $(row.cells[iCol]).children("a").click(function (e) { to .children("a").eq(0) or .children("a").eq(1) and .children("a").eq(2) to define binding to the first, second or third hyperlink ("edit"/"add"/"delete"). You should better to save $(row.cells[iCol]).children("a") in a variable and use .eq(1) with the variable.

One more way will be don't define any <a> an all and use for example <span> instead (with underlining decoration or with background image). In the case you don't need to suppress default hyperlink action and the click event will be bubble till the <table> element which define the grid body. So you can use onCellSelect or beforeSelectRow events to bind your JavaScript code. The Event (e parameter) of the events can be used to get all information about the clicked row and column. var $cell = $(e.target).closest('td') will get you the clicked cell, var $row = $cell.closest('tr.jqgrow') will get you the clicked row, $row.attr('id') will be the rowid and var iCol = $.jgrid.getCellIndex($cell[0]) get you the column index. The this.p.colModel[iCol].name is the name of the column which was clicked. You can read here more bout the way.

How you can see you have really many options which you can use. So you can choose the way which better corresponds your requirements.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Thanks a ton for your suggestions. This gave me some confidence. I will try to implement each approach and let you know which one i picked. – Kishan May 07 '12 at 13:11
  • @KishanKanugula: You are welcome! I hope you are not frustrated from so many possibilities. I decided to describe you many ways because first the best choice depend on the use case and seconds your question is very common. So I hope to help other users too who have the same problem. – Oleg May 07 '12 at 13:15
  • I tried using dynamiclink. I dont think i can use this as plugin rite? Because its binded to $.fn.fmatter which is defined in jqgrid.js. Do you mean to copy this code in jqrid.js? – Kishan May 07 '12 at 14:49
  • jqGrid uses `$.fn.fmatter`, `$.fn.jqGrid`, `$.fn.jqFilter`, `$.jgrid` and `$.fmatter` internally. You should just include `jQuery.jqGrid.dynamicLink.js` after `jquery.jqGrid.min.js`. After that `formatter: "dynamicLink"` can be used in the same way like any other predefined jqGrid formatter. – Oleg May 07 '12 at 15:32
  • Thanks a lot for help and also any help on following link which posted few weeks back http://stackoverflow.com/questions/10290510/jquery-sortable-replacing-items-rather-than-swapping-items. Your suggestion on this will helps a lot..thanks. – Kishan May 08 '12 at 02:18