Free-jqgrid - 如何在 beforeShowForm 方法中关闭编辑表单

Free-jqgrid - How to close edit form in beforeShowForm method

我使用的是 free-jqgrid 4.9.2 版本。

我想显示编辑表单取决于服务器端的逻辑。所以我决定使用 beforeShowForm 方法放置我的逻辑。但是我无法 hide/close 编辑表单。

beforeShowForm 方法 -

 beforeShowForm: function($form) {
   var rowId = jQuery(this).jqGrid('getGridParam', 'selrow');
   var rowData = jQuery(this).getRowData(rowId);
   //CALL SERVER SIDE & TEMPORARY LOGIC FOR NOW
   if (rowData.active == 0) {
     alert("Just diabling the model !");

     //LOGIC TO HIDE/CLOSE THE EDIT FORM ???

     //NOT WORKING - AS IT HIDES THE MODAL, WHEN I CLICK OTHER ROW EARLIER ROW DATA COMING !!
     //var idSelector = $.jgrid.jqID(this.p.id);
     //$.jgrid.hideModal("#FrmGrid_" +idSelector, {gbox: "#gbox_" + idSelector});

     //$form.hide(); NOT WORKING - this makes only form fields hide not complete dialog
     //$('#cData').trigger('click'); - NOT WORKING, WILL not because we are in beforeShowForm and will work in afterShowForm
     //$form.parent().find('#cData').trigger("click"); - NOT WORKING, WILL not because we are in beforeShowForm and will work in afterShowForm
     //jQuery('.ui-jqdialog-titlebar-close').trigger("click"); - WILL CLOSE ALL DIALOG, NOT RECOMMENDED !!
     //return [false,''];
   } else {
     //Don't do anything
   }
 },

完整的 jqGrid 代码 -

$(document).ready(
  function() {

    /**
     * Initiate i18n bundle
     */
    var localeProp = jQuery.i18n.prop;

    var baseColumnTemplate = {
      width: 120,
      searchoptions: {
        sopt: ['cn', 'eq', 'ne', 'bw', 'bn', 'nc', 'ew', 'en']
      }, //for Search/Filter functionality - specify the search options
      editoptions: {
        edittype: 'text',
        size: 30
      },
      editrules: {
        required: false,
        custom: true,
        custom_func: onlyAlphabetCheck
      }
    }
    var selectColumnTemplate = {
        width: 100,
        stype: "select", //if stype is enabled then sopt will not work - stype is needed only when search should have select option
        edittype: "select",
        formatter: "select"
      }
      /**
       * Application User Details tab
       */
    var $grid = $("#userGrid").jqGrid({
      //sortable: true,//Columns reordering need to be disabled for frozen column working
      //scroll: 1,//true scrolling rows - paging is not working when we enable scrolling. give fixed height then this will go good.. :)
      url: 'list_user_detail',
      datatype: 'json',
      colNames: [localeProp('userdetail.table.column.id'),
        localeProp('userdetail.table.column.username'),
        localeProp('userdetail.table.column.password'),
        localeProp('userdetail.table.column.active'),
        localeProp('userdetail.table.column.firstname'),
        localeProp('userdetail.table.column.lastname'),
        localeProp('userdetail.table.column.department'),
        localeProp('userdetail.table.column.email'),
        localeProp('userdetail.table.column.dob'),
        localeProp('userdetail.table.column.country'),
        localeProp('userdetail.table.column.role'),
        ""
      ],
      cmTemplate: {
        resizable: false,
        align: 'center',
        sortable: true,
        editable: true
      },
      colModel: [{
        name: 'id',
        width: 80,
        sorttype: 'integer',
        searchoptions: {
          sopt: ['eq', 'ne', 'le', 'lt', 'gt', 'ge'] //for filter functionality - specify the search options
        },
        editoptions: {
          readonly: true,
          size: 5
        }
      }, {
        name: "username",
        template: baseColumnTemplate,
        editrules: {
          required: true,
          custom_func: usernameCheck
        },
        formoptions: {
          label: localeProp('userdetail.table.form.label.username')
        }
      }, {
        name: "password",
        template: baseColumnTemplate,
        hidden: true,
        hidedlg: true, //to remove this column from column chooser as well
        //editrules are set as part of form edit validation so we can mark required for all mandatory fields
        editrules: {
          required: true,
          edithidden: true,
          custom_func: passwordCheck
        },
        formoptions: {
          label: localeProp('userdetail.table.form.label.password')
        }
      }, {
        name: "active",
        template: selectColumnTemplate,
        editoptions: {
          value: ":;1:Yes;0:No" //Default 0
        },
        cellattr: function(rowId, val, rawObject) {
          if (val == 1) {
            return " class='ui-state-useractive'";
          } else if (val == 0) {
            return " class='ui-state-userinactive'";
          }
        }
      }, {
        name: "firstname",
        template: baseColumnTemplate

      }, {
        name: "lastname",
        template: baseColumnTemplate

      }, {
        name: "department",
        template: baseColumnTemplate
      }, {
        name: "email",
        template: baseColumnTemplate,
        width: 220,
        editrules: {
          required: true,
          custom_func: emailCheck
        },
        formoptions: {
          label: localeProp('userdetail.table.form.label.email')
        }
      }, {
        name: "birthday",
        width: 120,
        searchoptions: {
          sopt: ['cn', 'eq', 'ne', 'bw', 'bn', 'nc', 'ew', 'en'],
          dataInit: function(e) {
            $(e).datepicker({
              dateFormat: 'dd-mm-yy',
              maxDate: new Date()
            });
          }
        }, //for Search/Filter functionality - specify the search options
        editoptions: {
          size: 10,
          dataInit: function(e) {
            $(e).datepicker({
              dateFormat: 'dd-mm-yy',
              maxDate: new Date()
            });
          }
        }
      }, {
        name: "country",
        template: baseColumnTemplate
      }, {
        name: "role",
        template: selectColumnTemplate,
        editoptions: {
          value: ":;ADMIN:Admin;USER:User" //Default User
        }
      }, {
        name: "oldPassword",
        width: 10,
        hidden: true,
        hidedlg: true //to remove this column from column chooser as well
      }],
      pager: true,
      iconSet: "fontAwesome",
      rowNum: 8,
      rownumbers: false, //Row numbers
      rowList: [8, 12, 20],
      height: 'auto',
      width: 'auto', //Autowidth
      loadonce: true,
      sortable: true,
      sortname: 'No',
      sortorder: 'desc',
      viewrecords: true,
      shrinkToFit: false,
      ignoreCase: true, //Case insensitive search
      gridview: true, //renders data more faster??
      //viewsortcols: true,//easily show what columns are sortable - With this sorting not working.
      caption: localeProp('userdetail.table.caption'),
      editurl: "edit_user_detail",
      multiselect: false,
      toppager: true, //Toolbar option
      cloneToTop: true //Toolbar option

    });

    // Navigator tab inside pager grid
    $grid.jqGrid('navGrid', '#userPager', {
      //General options
      edit: false,
      add: false,
      del: false,
      search: false,
      view: false,
      refresh: false,
      cloneToTop: true //Must for top tool bar - this will close all the pager items in top tool bar.
    });

    /*Search/Filter toolbar*/
    $grid.jqGrid('filterToolbar', {
      searchOperators: true,
      searchOnEnter: false,
      jqModal: false,
      multipleSearch: true,
      multipleGroup: true,
      recreateFilter: true,
      closeOnEscape: true,
      overlay: 0,
      stringResult: true
    });

    //Top Toolbar options & Buttons
    //before adding any buttons remove all the items copied/cloned from the bottom pager
    //TO make sure that buttons are placed in entire grid width
    $("#userGrid_toppager_center,#userGrid_toppager_right").hide();

    //Toolbar button to add a config
    $grid.jqGrid('navButtonAdd', '#userGrid_toppager', {
      caption: localeProp('userdetail.table.button.adduser'),
      title: localeProp('userdetail.table.title.add'),
      buttonicon: 'fa-user-plus',
      onClickButton: function() {
        jQuery(this).jqGrid('editGridRow', "new", {
          //Add options
          height: 'auto',
          width: 'auto',
          modal: true,
          addCaption: localeProp('userdetail.table.button.adduser'),
          processData: localeProp('application.common.message.processing'),
          recreateForm: true,
          reloadAfterSubmit: false,
          closeOnEscape: true,
          bottominfo: localeProp('application.common.message.mandatoryfields'),
          bSubmit: localeProp('application.common.button.save'),
          afterShowForm: function($form) {
            $form.closest(".ui-jqdialog").closest(".ui-jqdialog").position({
              my: 'center',
              at: 'center',
              of: window
            });
          },
          afterSubmit: refreshData, // Need to refresh the data in the table to reflect the primary key added to this table.
          closeAfterAdd: true
        });
      }
    });

    //Toolbar button to edit a config
    $grid.jqGrid('navButtonAdd', '#userGrid_toppager', {
      caption: localeProp('userdetail.table.button.edituser'),
      title: localeProp('userdetail.table.title.edit'),
      buttonicon: 'fa-users',
      onClickButton: function() {
        var gr = jQuery(this).jqGrid('getGridParam', 'selrow');
        if (gr != null)
          jQuery(this).jqGrid('editGridRow', gr, {
            //Edit options
            height: 'auto',
            width: 'auto',
            modal: true,
            editCaption: localeProp('userdetail.table.button.edituser'),
            processData: localeProp('application.common.message.processing'),
            recreateForm: true,
            bottominfo: localeProp('application.common.message.mandatoryfields'),
            bSubmit: localeProp('application.common.button.save'),
            reloadAfterSubmit: false,
            closeOnEscape: true,
            closeAfterEdit: true,
            afterShowForm: function($form) {
              $form.closest(".ui-jqdialog").closest(".ui-jqdialog").position({
                my: 'center',
                at: 'center',
                of: window
              });
            },
            beforeShowForm: function($form) {
              var rowId = jQuery(this).jqGrid('getGridParam', 'selrow');
              var rowData = jQuery(this).getRowData(rowId);
              //CALL SERVER SIDE & TEMPORARY LOGIC FOR NOW
              if (rowData.active == 0) {
                alert("Just diabling the model !");

                //LOGIC TO HIDE/CLOSE THE EDIT FORM ???

                //NOT WORKING - AS IT HIDES THE MODAL, WHEN I CLICK OTHER ROW EARLIER ROW DATA COMING !!
                //var idSelector = $.jgrid.jqID(this.p.id);
                //$.jgrid.hideModal("#FrmGrid_" +idSelector, {gbox: "#gbox_" + idSelector});

                //$form.hide(); NOT WORKING - this makes only form fields hide not complete dialog
                //$('#cData').trigger('click'); - NOT WORKING, WILL not because we are in beforeShowForm and will work in afterShowForm
                //$form.parent().find('#cData').trigger("click"); - NOT WORKING, WILL not because we are in beforeShowForm and will work in afterShowForm
                //jQuery('.ui-jqdialog-titlebar-close').trigger("click"); - WILL CLOSE ALL DIALOG, NOT RECOMMENDED !!
                //return [false,''];
              } else {
                //Don't do anything
              }
            },
            afterSubmit: refreshData // Need to refresh the data in the table to reflect the hashed password
          });
        else {
          $.jgrid.info_dialog.call(
            this,
            localeProp('userdetail.table.dialog.message.caption'), // dialog title
            localeProp('userdetail.table.dialog.message.selectrow'), // text inside of dialog
            localeProp('application.common.button.close'), // text in the button
            {
              left: 500,
              top: 250
            }

          );
        }
      }
    });

    //Toolbar button to delete a user
    $grid.jqGrid('navButtonAdd', '#userGrid_toppager', {
      caption: localeProp('userdetail.table.button.deleteuser'),
      title: localeProp('userdetail.table.title.delete'),
      buttonicon: 'fa-user-times',
      onClickButton: function() {
        var gr = jQuery(this).jqGrid('getGridParam', 'selrow');
        if (gr != null)
          jQuery(this).jqGrid('delGridRow', gr, {
            reloadAfterSubmit: false,
            closeOnEscape: true
          });
        else {
          $.jgrid.info_dialog.call(
            this,
            localeProp('userdetail.table.dialog.message.caption'), // dialog title
            localeProp('userdetail.table.dialog.message.selectrow'), // text inside of dialog
            localeProp('application.common.button.close'), // text in the button
            {
              left: 500,
              top: 250
            }
          );
        }
      }
    });

    //Column chooser button in top toolbar
    $grid.jqGrid('navButtonAdd', '#userGrid_toppager', {
      caption: localeProp('application.common.button.columns'),
      title: localeProp('userdetail.table.title.choosecolumn'),
      buttonicon: 'fa-columns',
      onClickButton: function() {
        jQuery(this).jqGrid('columnChooser');
      }
    });

    //Button to toggle toolbar search/filter option
    $grid.jqGrid('navButtonAdd', "#userGrid_toppager", {
      caption: localeProp('application.common.button.search'),
      title: localeProp('userdetail.table.title.search'),
      buttonicon: 'fa-toggle-on',
      onClickButton: function() {
        $grid[0].toggleToolbar();
      }
    });

    //Refresh Button as auto refresh not exists for user detail
    $grid.jqGrid('navButtonAdd', '#userGrid_toppager', {
      caption: localeProp('application.common.button.refresh'),
      title: localeProp('userdetail.table.title.refreshuserdetail'),
      buttonicon: 'fa fa-cog fa-spin',
      onClickButton: function() {
        refreshData();
      }
    });

    //Frozen columns - NOT needed as of now as no. of columns are limited.
    //$grid.jqGrid('setFrozenColumns');

    //Grid resize
    $grid.jqGrid('gridResize', {
      minWidth: 550,
      maxWidth: 1300,
      minHeight: 80,
      maxHeight: 350
    });

    /**
     * Function to refresh the data after a new row inserted in DB. If
     * not then when we update the same row again, because of no primary
     * key reflected in client side, a fresh row will be inserted. Also
     * if we are refreshing the grid, then immediate delete of this row
     * will fail because again primary key(i.e. id) not reflected in the
     * client side
     *
     * NOT SURE IS THERE ANY OTHER BETTER WAY TO DO THIS !!!!
     */
    function refreshData() {
      $grid.jqGrid("setGridParam", {
        datatype: 'json',
        url: 'list_user_detail',
        page: 1
      }).trigger("reloadGrid");
      return [true, '']; //TO make sure that control goes back to jqGrid inbuild configs like closeafterAdd etc.
    }

    //Username Validation checks !!
    function usernameCheck(value) {
      if (checkLength(value, 6, 50) && checkRegexp(value, /^[a-z]([0-9a-z_.])+$/i)) {
        return [true, "", ""];
      } else {
        return [false, localeProp('userdetail.validation.message.username'), ""];
      }
    }

    //Password Validation checks !!
    function passwordCheck(value) {
      if (checkLength(value, 6, 60)) {
        return [true, "", ""];
      } else {
        return [false, localeProp('userdetail.validation.message.password'), ""];
      }
    }

    //Firstname & Lastname Validation checks !!
    function onlyAlphabetCheck(value) {
      if (checkLength(value, 1, 50) && checkRegexp(value, /^[a-z]([a-z ])+$/i)) {
        return [true, "", ""];
      } else {
        return [false, localeProp('userdetail.validation.message.firstname'), ""];
      }
    }

    //Email Validation checks !!
    function emailCheck(value) {
      if (checkLength(value, 6, 100) && checkRegexp(value, /^((([a-z]|\d|[!#$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i)) {
        return [true, "", ""];
      } else {
        return [false, localeProp('userdetail.validation.message.email'), ""];
      }
    }

    //Birthday Validation checks !!
    function birthdayCheck(value) {
      var now = new Date();
      if (value < now) {
        return [true, "", ""];
      } else {
        return [false, localeProp('userdetail.validation.message.dob'), ""];
      }
    }

    /*Check length of particular field*/
    function checkLength(o, min, max) {
      if (o.length > max || o.length < min) {
        return false;
      } else {
        return true;
      }
    }

    /*Check regex/format of particular field*/
    function checkRegexp(o, regexp) {
      if (!(regexp.test(o))) {
        return false;
      } else {
        return true;
      }
    }


  });

首先,jqGrid 调用 beforeShowForm before 显示 mill 的编辑,它直接在调用 beforeShowForm 之前显示 for。如果意味着在 beforeShowForm 内部调用 $.jgrid.hideModal 为时过早。而不是可以在 afterShowForm 回调中执行此操作。

我查看了您发布的代码,在我看来,将表单隐藏在 beforeShowFormafterShowForm 回调内部都不是最佳选择。您目前所做的是使用 edit: falseadd: false 选项调用 navGrid。您稍后添加 "Add" 和 "Edit" 按钮,并在获取所选行的 id 后直接在 onClickButton 内部调用 editGridRow

因此我建议您在 onClickButton 回调中移动关闭表单的逻辑。最好测试所选行是否符合您的所有自定义条件 (active !== 0) 并仅在 情况下调用 editGridRow 。它将不需要关闭 add/edit 表单。

您可以在 the old answer and in this one 中找到另一种实施思路。您可以根据您的自定义条件 隐藏 禁用 "Add" 或 "Edit" 按钮。例如,可以实现 onSelectRow 回调,其中 enable/disables/hide/show "Add" 或 "Edit" 基于 active 列的值。如果未选择任何行,则可以禁用或隐藏 Edit/Delete 按钮。为了简化按钮的使用,我建议您使用 navButtonAddid 选项将 id 分配给每个按钮。