jqGrid级联下拉更改事件不会触发

时间:2012-11-11 13:33:17

标签: javascript javascript-events jqgrid jqgrid-asp.net

Oleg和许多网站帮助我一直致力于在jqGrid中获取级联数据绑定下拉功能

我有三个下拉菜单:客户>项目>任务。更改客户应使用该客户项目重新加载项目。更改项目应使用该项目任务重新加载任务。

我实际上让Project通过在Customer中创建一个更改事件处理程序来重新加载客户任务,然后在客户端调用getJson,然后使用新选项替换Project下拉列表的内容。它很棒。

然后我将相同的逻辑应用于项目下拉列表,但Project事件 not 似乎无法触发。我在更改项目下拉列表时观察到以下内容:

  1. 任务下拉列表不会更改
  2. 未调用Task Json控制器事件(它意味着在项目更改事件中由getJSON调用)
  3. 在Firebug中,在网络监视器中,不会显示对Task Json控制器事件的​​调用和响应。
  4. 在Firebug中,它没有遇到我在Project change event handler
  5. 中设置的断点

    然而,客户事件处理程序运行良好,并在我更改客户时按预期执行上述所有4点。

    我很确定它没有针对项目下拉列表触发更改事件。

    如果我运行网页并编辑并更改项目下拉值作为我的第一个操作,它不会触发项目事件处理程序,因此我认为不是重置Project事件处理程序的Customer事件。

    那么,有没有人知道为什么我的客户更改事件调用但我的项目不是?

    有没有办法可以检查DOM或其​​他东西,看看我的事件是否已在运行时附加?这是它的工作方式吗?

    我正在使用jqGrid 4.4.1

    我的jqGrid以这种方式设置:

    • 使用内联编辑
    • 单击以选择dblclick进行编辑
    • 日期选择器附加了日期列
    • 编辑后,我从隐藏字段中获取select db键值,但我希望我可以删除它。
    • 我有三个选择彼此相邻

    这是我的jqGrid定义

    $(document).ready(
        function () {
            // This is executed as soon as the DOM is loaded and before the page contents are loaded
            var lastsel;
            // $ is short for JQuery which is in turn a super overloaded function that does lots of things.
            // # means select an element by its ID name, i.e. below we have <table id="ts"
            // .jqGrid means attach a jqGrid 'thing' to all elements that have ts as their element name (there's only one)
            // jqGrid is a thing defined in the jqGrid javascript file
            $("#ts").jqGrid({
                //=============
                // Grid Setup
                url: 'Timesheet/GridData/',
                datatype: 'json',
                mtype: 'GET',
                pager: $('#pager'),
                rowNum: 30,
                rowList: [10, 20, 30, 40, 80],
                viewrecords: true,
                caption: 'Timesheet',
                height: 450,
                // Column definition
                colNames: ['hCustomer_ID', 'hProject_ID', 'hTask_ID', 'Date', 'Customer', 'Project', 'Task', 'Description', 'Hours', '$'],
                colModel: [
                  { name: 'hCustomer_ID', index: 'hCustomer_ID', editable: false, hidden: true },
                  { name: 'hProject_ID', index: 'hProject_ID', editable: false, hidden: true },
                  { name: 'hTask_ID', index: 'hTask_ID', editable: false, hidden: true },
                  { name: 'tsdate', index: 'tsdate', width: 80, editable: true, datefmt: 'yyyy-mm-dd' },
                // Defintion for customer column
                  {name: 'Customer', index: 'Customer', width: 250, align: 'left', editable: true, edittype: "select",
                  editoptions: {
                      // Default URL used to populate drop down when the column goes into edit mode  
                      dataUrl: 'Timesheet/CustomerList',
                      dataEvents: [
                          {
                              // this is the change handler. This is called when the customer is changed
                              type: 'change',
                              fn: function (e) {
                                  // get a reference to the project and task drop downs on this same row
                                  var eProject = '#' + $(this).attr("id").replace("_Customer", "_Project");
                                  var eTask = '#' + $(this).attr("id").replace("_Customer", "_Task");
                                  // Call getJSON to get data from a URL and process it with a callback function
                                  $.getJSON(
                                  // the URL to call
                                    'Timesheet/ProjectListJSON',
                                  // the parameter(s) to pass to the URL
                                    {Customer_ID: this.value },
                                  // The callback function. The results of the JSON call are passed into jData
                                    function (jData) {
                                        var selectHtml = ""
                                        // Repopulate the project drop down with the results of the JSON call
                                        $.each(
                                            jData,
                                            function (jdIndex, jdData) {
                                                selectHtml = selectHtml + "<option value='" + jdData.Value + "'>" + jdData.Text + "</option>";
                                            });
                                        // dont use innerHTML as it is not supported properly by IE
                                        // insted use jQuery html to change the select list options
                                        $(eProject).html(selectHtml);
                                        // blank out tasks
                                        $(eTask).html("");
                                    } // END getJSON callback function definition
                                  ); // END getJSON function call
                              } // END change event definition
                          }] // END dataEvents definition
                  } // END editoptions list
              }, // END Customer jqGrid field definition
                // Definition for Project drop down
              {name: 'Project', index: 'Project', width: 250, align: 'left', editable: true, edittype: "select",
              editoptions: {
                  dataUrl: 'Timesheet/ProjectList',
                  dataEvents: [
                          {
                              type: 'change',
                              fn: function (e) {
                                  var eTask = '#' + $(this).attr("id").replace("_Project", "_Task");
                                  $.getJSON(
                                    'Timesheet/TaskListJSON',
                                    { CustomerProject_ID: this.value },
                                    function (jData) {
                                        var selectHtml = "";
                                        $.each(
                                            jData,
                                            function (jdIndex, jdData) {
                                                selectHtml = selectHtml + "<option value='" + jdData.Value + "'>" + jdData.Text + "</option>";
                                            });
                                            $(eTask).html(selectHtml);
                                    } // END getJSON callback function definition
                                  ); // END getJSON function call
                              } // END change event handler definition
                          }] // END dataevents definition
              } // END editoptions list
          }, // END Project jqGrid field definition
                  {name: 'Task', index: 'Task', width: 250, align: 'left', editable: true, edittype: "select", editoptions: { dataUrl: 'Timesheet/TaskList'} },
                  { name: 'Desc', index: 'Desc', width: 300, align: 'left', editable: true },
                  { name: 'Hours', index: 'Hours', width: 50, align: 'left', editable: true },
                  { name: 'Charge', index: 'Charge', edittype: 'checkbox', width: 18, align: 'center', editoptions: { value: "0:1" }, formatter: "checkbox", formatoptions: { disabled: false }, editable: true }
                ],
                //=============
                // Grid Events
                // when selecting, undo anything else
                onSelectRow: function (rowid, iRow, iCol, e) {
                    if (rowid && rowid !== lastsel) {
                        // $(this).jqGrid('restoreRow', lastsel);
                        lastsel = rowid;
                    }
                },
                // double click to edit
                ondblClickRow: function (rowid, iRow, iCol, e) {
                    // browser independent stuff
                    if (!e) e = window.event;
                    var element = e.target || e.srcElement
    
                    // When editing, change the drop down datasources to filter on the current parent
                    $(this).jqGrid('setColProp', 'Project', { editoptions: { dataUrl: 'Timesheet/ProjectList?Customer_ID=' + $(this).jqGrid('getCell', rowid, 'hCustomer_ID')} });
                    $(this).jqGrid('setColProp', 'Task', { editoptions: { dataUrl: 'Timesheet/TaskList?CustomerProject_ID=' + $(this).jqGrid('getCell', rowid, 'hProject_ID')} });
    
                    // Go into edit mode (automatically moves focus to first field)
                    // Use setTimout to apply the focus and datepicker after the first field gets the focus
                    $(this).jqGrid(
                        'editRow',
                        rowid,
                        {
                            keys: true,
                            oneditfunc: function (rowId) {
                                setTimeout(function () {
                                    $("input, select", element).focus();
                                    $("#" + rowId + "_tsdate").datepicker({ dateFormat: 'yy-mm-dd' });
                                }, 50);
                            }
                        }
                    );
    
                },  // end ondblClickRow event handler
                postData:
                    {
                        startDate: function () { return $('#startDate').val(); }
                    }
            }); // END jQuery("#ts").jqGrid
    
            $("#ts").jqGrid('navGrid', '#pager', { view: false, edit: false, add: false, del: false, search: false });
            $("#ts").jqGrid('inlineNav', "#pager");
    
        });                                       // END jQuery(document).ready(function () {
    

    此处有固定代码

    我将更改事件处理程序定义移出了列定义并进入了dblclick事件处理程序。它仍然不完美。我确信每次附加事件处理程序都会有一些开销,当Customer更改时,它会更新并选择第一个Project,但会清除任务。

    $(document).ready(
        function () {
            // This is executed as soon as the DOM is loaded and before the page contents are loaded
            var lastsel;
            // $ is short for JQuery which is in turn a super overloaded function that does lots of things.
            // # means select an element by its ID name, i.e. below we have <table id="ts"
            // .jqGrid means attach a jqGrid 'thing' to all elements that have ts as their element name (there's only one)
            // jqGrid is a thing defined in the jqGrid javascript file
            $("#ts").jqGrid({
                //=============
                // Grid Setup
                url: 'Timesheet/GridData/',
                datatype: 'json',
                mtype: 'GET',
                pager: $('#pager'),
                rowNum: 30,
                rowList: [10, 20, 30, 40, 80],
                viewrecords: true,
                caption: 'Timesheet',
                height: 450,
                // Column definition
                colNames: ['hCustomer_ID', 'hProject_ID', 'hTask_ID', 'Date', 'Customer', 'Project', 'Task', 'Description', 'Hours', '$'],
                colModel: [
                  { name: 'hCustomer_ID', index: 'hCustomer_ID', editable: false, hidden: true },
                  { name: 'hProject_ID', index: 'hProject_ID', editable: false, hidden: true },
                  { name: 'hTask_ID', index: 'hTask_ID', editable: false, hidden: true },
                  { name: 'tsdate', index: 'tsdate', width: 80, editable: true, datefmt: 'yyyy-mm-dd' },
                // Defintion for customer column
                  {name: 'Customer', index: 'Customer', width: 250, align: 'left', editable: true, edittype: "select",
                  editoptions: {
                      // Default URL used to populate drop down when the column goes into edit mode  
                      dataUrl: 'Timesheet/CustomerList',
                      dataEvents: [
                          {
                              // this is the change handler. This is called when the customer is changed
                              type: 'change',
                              fn: function (e) {
                                  // get a reference to the project and task drop downs on this same row
                                  var eProject = '#' + $(this).attr("id").replace("_Customer", "_Project");
                                  var eTask = '#' + $(this).attr("id").replace("_Customer", "_Task");
                                  // Call getJSON to get data from a URL and process it with a callback function
                                  $.getJSON(
                                  // the URL to call
                                    'Timesheet/ProjectListJSON',
                                  // the parameter(s) to pass to the URL
                                    {Customer_ID: this.value },
                                  // The callback function. The results of the JSON call are passed into jData
                                    function (jData) {
                                        var selectHtml = ""
                                        // Repopulate the project drop down with the results of the JSON call
                                        $.each(
                                            jData,
                                            function (jdIndex, jdData) {
                                                selectHtml = selectHtml + "<option value='" + jdData.Value + "'>" + jdData.Text + "</option>";
                                            });
                                        // dont use innerHTML as it is not supported properly by IE
                                        // insted use jQuery html to change the select list options
                                        $(eProject).html(selectHtml);
                                        // clear task list
                                        $(eTask).html(""); 
                                    } // END getJSON callback function definition
                                  ); // END getJSON function call
                              } // END change event definition
                          }] // END dataEvents definition
                  } // END editoptions list
              }, // END Customer jqGrid field definition
                // Definition for Project drop down
                  {name: 'Project', index: 'Project', width: 250, align: 'left', editable: true,
                  edittype: "select", editoptions: { dataUrl: 'Timesheet/ProjectList'}
              }, // END Project jqGrid field definition
                  {name: 'Task', index: 'Task', width: 250, align: 'left', editable: true, edittype: "select", editoptions: { dataUrl: 'Timesheet/TaskList'} },
                  { name: 'Desc', index: 'Desc', width: 300, align: 'left', editable: true },
                  { name: 'Hours', index: 'Hours', width: 50, align: 'left', editable: true },
                  { name: 'Charge', index: 'Charge', edittype: 'checkbox', width: 18, align: 'center', editoptions: { value: "0:1" }, formatter: "checkbox", formatoptions: { disabled: false }, editable: true }
                ],
                //=============
                // Grid Events
                // when selecting, undo anything else
                onSelectRow: function (rowid, iRow, iCol, e) {
                    if (rowid && rowid !== lastsel) {
                        // $(this).jqGrid('restoreRow', lastsel);
                        lastsel = rowid;
                    }
                },
                // double click to edit
                ondblClickRow: function (rowid, iRow, iCol, e) {
                    // browser independent stuff
                    if (!e) e = window.event;
                    var element = e.target || e.srcElement
    
                    // When editing, change the drop down datasources to filter on the current parent
                    // By default tasks are limited to the current project
                    $(this).jqGrid('setColProp', 'Task', { editoptions: { dataUrl: 'Timesheet/TaskList?CustomerProject_ID=' + $(this).jqGrid('getCell', rowid, 'hProject_ID')} });
    
                    // By default projects are limited to the current Customer (dataUrl)
                    // Also attach event handler to autopopulate tasks (dataEvents)
                    $(this).jqGrid('setColProp', 'Project', {
                        //                    editoptions: { dataUrl: 'Timesheet/ProjectList?Customer_ID=' + $(this).jqGrid('getCell', rowid, 'hCustomer_ID')} });
                        editoptions: {
                            dataUrl: 'Timesheet/ProjectList?Customer_ID=' + $(this).jqGrid('getCell', rowid, 'hCustomer_ID'),
                            dataEvents: [
                                  {
                                      type: 'change',
                                      fn: function (e) {
                                          var eTask = '#' + $(this).attr("id").replace("_Project", "_Task");
                                          $.getJSON(
                                            'Timesheet/TaskListJSON',
                                            { CustomerProject_ID: this.value },
                                            function (jData) {
                                                var selectHtml = "";
                                                $.each(
                                                    jData,
                                                    function (jdIndex, jdData) {
                                                        selectHtml = selectHtml + "<option value='" + jdData.Value + "'>" + jdData.Text + "</option>";
                                                    });
                                                $(eTask).html(selectHtml);
                                            } // END getJSON callback function definition
                                          ); // END getJSON function call
                                      } // END change event handler definition
                                  }] // END dataevents definition
                        } // END editoptions list
                    } // END data to be applied to setColProp
                    ); // END jqGrid setColProp
    
                    // Go into edit mode (automatically moves focus to first field)
                    // Use setTimout to apply the focus and datepicker after the first field gets the focus
                    $(this).jqGrid(
                        'editRow',
                        rowid,
                        {
                            keys: true,
                            oneditfunc: function (rowId) {
                                setTimeout(function () {
                                    $("input, select", element).focus();
                                    $("#" + rowId + "_tsdate").datepicker({ dateFormat: 'yy-mm-dd' });
                                }, 50);
                            }
                        }
                    );
    
                },  // end ondblClickRow event handler
                postData:
                    {
                        startDate: function () { return $('#startDate').val(); }
                    }
            }); // END jQuery("#ts").jqGrid
    
            $("#ts").jqGrid('navGrid', '#pager', { view: false, edit: false, add: false, del: false, search: false });
            $("#ts").jqGrid('inlineNav', "#pager");
    
        });                                         // END jQuery(document).ready(function () {
    

2 个答案:

答案 0 :(得分:2)

我认为您遇到问题的原因是jQuery.empty的使用(请参阅第eTask.empty();行和eProject.empty();行)。如果您检查jQuery.empty的说明,您会发现以下内容:

  

为了避免内存泄漏,jQuery删除了其他构造,如数据   和删除之前来自子元素的事件处理程序   元素本身。

     

如果要删除元素而不破坏其数据或事件   处理程序(以便以后可以重新添加),请改用.detach()。

在我看来,在你的情况下,可以只构造所有<option>元素串联的字符串。然后,您可以使用jQuery.html将所有旧选项替换为新选项。您不仅可以解决主要问题,还可以获得一些性能优势。您应该了解的问题是,如果您更改页面Web浏览器上的某些元素,则必须重新计算页面上所有现有元素的位置或样式。因此,如果您在循环中调用jQuery.append,那么每个调用将至少跟随reflow,这是扩展的。因此,您应该更好地编写程序,以便减少页面上的更改次数。如果您首先将innerHTML<select>元素构造为HTML字符串,并使用 jQuery.html的一个调用(或仅设置innerHTML属性DOM元素)您将获得性能提升。

我在程序中看到的另一个问题是初始化“项目”和“任务”中的选择。如果用户开始编辑该行,则选择元素将填充dataUrl: 'Timesheet/TaskList'dataUrl: 'Timesheet/ProjectList'。因此,您将拥有所有项目和任务,而不仅仅是'Customer'的项目以及基于'Customer''Project'值的任务。我认为您必须在编辑开始之前设置行相关的初始值dataUrl 。在表单编辑的情况下,您可以在onInitializeForm回调中执行此操作。如果您使用内联编辑,则应在调用editRow之前执行相同的

我建议您仔细检查来自the demothe answer代码。它不使用dataUrl,但会多次更改value属性。更改value属性将在您的情况下与dataUrl

的设置相对应

答案 1 :(得分:0)

好的,问题是在ondblClickRow事件处理程序中我设置了editoptions / dataUrl属性。由于此时我还没有指定editoptions / dataEvents属性,所以它基本上覆盖了静态事件处理程序。

在ondblClickRow事件处理程序中,我只覆盖了Project和Tasks下拉列表,这解释了为什么删除了Project处理程序而不是Customer客户端。

对Oleg道歉:我没有在开始时发布完整的代码,因此我没有包含双击事件。

无论如何Oleg如果你可以建议我如何保存事件处理程序我可以给你答案。否则我会将此作为答案,即使你的帮助非常宝贵。我猜我可能需要将事件处理程序定义下移到dblclick事件处理程序而不是列定义?