How can I set up a contextMenu for my jqGrid?
Asked Answered
U

1

3

I have a jqGrid for internal use on our site that lists all our users. On each user/row, I would like to be able to apply various options (depending on the data in that row). Instead of adding navbuttons to the pager, it would make more sense to have a context menu that appears on right-click of a row.

We currently have this jQuery contextMenu plugin imported on our site, so it would be preferable to somehow integrate that into my jqGrid.

My jqGrid scaled down to basics looks something like this:

$("#users").jqGrid({
    datatype: 'json',
    url: 'myMethodURL',
    gridview: true,
    colModel: [
        {name: 'id', label: 'User ID', hidden:true},
        {name: 'lastname', label: 'Last Name'},
        {name: 'firstname', label: 'First Name'},
        {name: 'status', label: 'Status', stype: 'select', searchoptions: {value: ':All;ACTIVE:Active;INACTIVATED:Inactive;PENDING APPROVAL:Pending Approval;'}},
        ... more fields ...
      ],
    height:'auto',
    autowidth:true,
    caption:'Users',
    rowNum:20,
    rowList:[10,20,50],
    sortorder:'asc',
    sortname: 'lastname',
    ignoreCase: true, // case-insensitive filtering
    pager: '#pager',
    jsonReader: {
        root: "ROWS", //our data
        page: "PAGE", //current page
        total: "TOTAL", //total pages
        records:"RECORDS", //total records
        cell: "", //not used
        id: "0" //will default first column as ID
    },
    postData: postData
});
$("#users").jqGrid("filterToolbar", {searchOnEnter: true});

Some of the options I need in the context menu:

  1. Activate OR Inactivate (depending on if user is currently active/inactive - basically need a toggle)
  2. Process pending user (should ONLY show up if user status is "pending")
  3. Edit user info
  4. Send reset password link

How can I set up a context menu with variable options (dependent on that particular row's values), and define what happens when an option is clicked?

Unboned answered 5/1, 2016 at 9:7 Comment(0)
P
2

In general the usage of the jQuery contextMenu plugin with jqGrid seems to me very simple. You can just bind the menu to the grid body. One need just know that the rowid is the value of id attribute of <tr> element and tr elements which have the real data have the class .jqgrow.

Thus the code could be like below

$("#users").jqGrid({
    datatype: 'json',
    ...
}).contextMenu({
    selector: ".jqgrow", 
    build: function ($trigger, e) {
        // this callback is executed every time the menu is to be shown
        // its results are destroyed every time the menu is hidden
        // e is the original contextmenu event

        var $tr = $(e.target).closest("tr.jqgrow"),
            rowid = $tr.attr("id"),
            item = $grid.jqGrid("getRowData", rowid);

        // item contains now the data of the row and we can
        // build the context menu dynamically
        if (item.status === "ACTIVE") {
            return {
                callback: function (key, options) {
                    var m = "clicked: " + key + " on rowid=" + rowid +
                            " (" + item.firstname + " " + item.lastname + ")";
                    alert(m); 
                },
                items: {
                    edit: {name: "Edit", icon: "edit"},
                    cut: {name: "Cut", icon: "cut"},
                    copy: {name: "Copy", icon: "copy"},
                    paste: {name: "Paste", icon: "paste"},
                    delete: {name: "Delete", icon: "delete"},
                    sep1: "---------",
                    quit: {name: "Quit", icon: function($element, key, item) {
                            return 'context-menu-icon context-menu-icon-quit';
                          }}
                }
            };
        } else {
            return {
                callback: function (key, options) {
                    var m = "clicked: " + key + " on rowid=" + rowid +
                            " (" + item.firstname + " " + item.lastname + ")";
                    alert(m); 
                },
                items: {
                    delete: {name: "Delete", icon: "delete"},
                    sep1: "---------",
                    quit: {name: "Quit", icon: function($element, key, item) {
                            return 'context-menu-icon context-menu-icon-quit';
                          }}
                }
            };
        }
    }
});

See the demo https://jsfiddle.net/OlegKi/37rb593h/. You can modify the code of build callback to any your requirements.

Primitive answered 5/1, 2016 at 11:51 Comment(5)
Thanks, this looks great! I'm going to see if I can consolidate the dynamic "items" code so that I don't have to repeat all the menu options for every logic change (only individual menu items will need to change), but this is a very helpful starting point and example.Unboned
@froadie: You are welcome! I'm not sure whether you knows the another plugin: createContexMenuFromNavigatorButtons. Typically I add buttons in the navigator bar for different actions. It's practical for supporting of touch devices for example. One can hide/disable some buttons depend on selected row. The method createContexMenuFromNavigatorButtons build context menu based on active buttons of nav.bar. Look at "Save" menu item of context menu of the demo created for the answerPrimitive
I'm confused about the version of the contextmenu plugin in the CDN you used in your jsfiddle. It seems to be version 2.0.1 but the latest version available for download is 1.6.6 ...Unboned
@froadie: You post me the link to plugins, which is obsolete since more as one year. The old plugins site is still available, but it's readonly. jQuery recommend to use npmjs.com, but bower.io is well known too. The links on plugins contains the reference to GitHub, which is the origin of the development. The developer uses not fill standard version numbers for git tags (2.0.1 instead of v2.0.1), but all the versions exists here. You can download it or use from CDN.Primitive
@froadie: If you write application which is available from internet, that CDN is the best choice. I'm don't know, which development framework you use, but the modern way for intranet application is like here, where one uses <script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js" asp-fallback-src="~/lib/jquery/dist/jquery.min.js" asp-fallback-test="window.jQuery"></script>. In other words one should use CDN as the main source and to use the local file as fallback source.Primitive

© 2022 - 2024 — McMap. All rights reserved.