Search code examples
javascriptjqueryasp.netjqgridvisual-web-developer-2010

JQGrid custom formatter - edit/save/cancel without formatter: 'action'


I am currently working with asp.net to develop a page where the user will interact with a jqgrid version 4.4.4. Because of the version, I cannot use formatter: 'action'. I have a custom formatter in place which has displayed an edit/save link.

I currently have this

return "<a href='javascript:void(0)' class='anchor usergroup_name link' onclick=\"editRow('" + rowobject.id + "')\">" + 'edit' + "</a>" +" | "
          +"<a href='javascript:void(0)' class='anchor usergroup_name link' onClick=\"saveRow('" + rowobject.id + "')\">" + 'save' + "</a>";

This code does add a edit/save button which has the ability to edit/save rows. However, I was looking to improve functionality by only showing one of these at a time. For example, if the user clicks edit, then save/cancel will appear and edit will disappear.

To do this, I tried giving the html links an id, but then only the first row will dissapear after doing $('id').hide().

Is there either a way to give each link a unique id, or is there a better way to do this?

Thank you for your help!!


Solution

  • jqGrid 4.4.4 is more as five and half years old! It isn't supported since a long time. I guess that you get jqGrid 4.4.4 via NuGet package jQuery.jqGrid. In the case, I'd recommend you uninstall the package and install free-jqGrid 4.15.4 instead. After that you can use formatter: "actions" or template: "actions".

    If you still want to understand how you can implement your requirements using custom formatter, then you have some alternatives. The first way would be to use your old code, but to modify the call of editRow (or saveRow)

    return "<a href='javascript:void(0)' class='anchor usergroup_name link' onclick=\"editRow('" + rowobject.id + "')\">" + 'edit' + "</a>" +" | "
          +"<a href='javascript:void(0)' class='anchor usergroup_name link' onClick=\"saveRow('" + rowobject.id + "')\">" + 'save' + "</a>";
    

    to

    return "<a href='javascript:void(0)' class='anchor usergroup_name link' onclick=\"editRow.call(this,'" + rowobject.id + "')\">edit</a>"+
          "<a style='display:none' href='javascript:void(0)' class='anchor usergroup_name link' onClick=\"saveRow.call(this,'" + rowobject.id + "')\">save</a>";
    

    onclick method will be called with this initialized to the DOM element of <a>, which the user clicked.

    Inside of your global functions editRow and saveRow you can use $(this).next().show(); or $(this).prev().show(); to show the second link and to use $(this).hide() to hide the current link. The simplest code of editRow and saveRow could be the following:

    function editRow (rowid) {
        $(this).hide()
            .next().show()
            .closest(".ui-jqgrid-btable").jqGrid("editRow", rowid);
    }
    function saveRow (rowid) {
        $(this).hide()
            .prev().show()
            .closest(".ui-jqgrid-btable").jqGrid("saveRow", rowid);
    }
    

    One more way will be don't use any inline onclick attributes at all. The click event supports event bubbling. It means that a click inside of any DOM element of the grid propagates the event the the tree of parents. Thus it's enough to define click event on the main <table> element of the grid. jqGrid does that already. One can use beforeSelectRow callback function which will be called inside of click event handler registered by jqGrid. The target property of the Event object (the second parameter of beforeSelectRow) will be the clicked element. Thus you can just verify whether e.target has the class usergroup_name, which you use for your links and, if it's so, do your main job: start editRow (or saveRow), hide/show the links and so on. Look at the old answer, which demonstrates the approach.