簡體   English   中英

jqGrid 級聯下拉更改事件不會觸發

[英]jqGrid cascading drop down change event does not fire

在 Oleg 和許多網站的幫助下,我一直致力於讓級聯數據綁定下拉列表在 jqGrid 中運行

我有三個下拉菜單:客戶 > 項目 > 任務。 更改客戶應使用該客戶項目重新加載項目。 更改項目應使用該項目任務重新加載任務。

通過在 Customer 中創建更改事件處理程序,我實際上已經讓 Project 重新加載該 Customer 任務,該處理程序反過來針對 URL 調用getJson ,然后用新選項替換 Project 下拉列表的內容。 它工作得很好。

然后我將同樣的邏輯應用到 Project 下拉菜單,但 Project 事件似乎沒有觸發。 在更改項目下拉菜單時,我觀察到以下內容:

  1. 任務下拉不會改變
  2. 未調用 Task Json 控制器事件(它旨在由項目更改事件中的getJSON調用)
  3. 在 Firebug 中,在網絡監視器中,不會出現對 Task Json 控制器事件的​​調用和響應。
  4. 在 Firebug 中,它不會遇到我在項目更改事件處理程序中設置的斷點

然而,客戶事件處理程序完美運行,並在我更改客戶時按預期執行上述所有 4 點。

我相當確定它不會針對項目下拉列表觸發更改事件。

如果我運行網頁並編輯和更改項目下拉值作為我的第一個操作,它不會觸發項目事件處理程序,所以我認為它不是客戶事件重置項目事件處理程序。

那么,有誰知道為什么我的 Customer change 事件調用,而我的 Project one 沒有調用?

有沒有辦法可以檢查 DOM 或其他東西,看看我的事件是否已在運行時附加? 這是它的工作方式嗎?

我正在使用 jqGrid 4.4.1

我的 jqGrid 是這樣設置的:

  • 使用內聯編輯
  • 單擊以選擇 dbl 單擊以進行編輯
  • 日期選擇器附加到日期列
  • 編輯后,我從隱藏字段中獲取了 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 更改時,它會更新並選擇第一個項目但清除任務。

$(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 () {

我想您遇到問題的原因是jQuery.empty的使用(請參閱eTask.empty();eProject.empty(); )。 如果您檢查jQuery.empty的描述,您會發現以下內容:

為了避免內存泄漏,jQuery 在刪除元素本身之前從子元素中刪除了其他構造,例如數據和事件處理程序。

如果您想刪除元素而不破壞它們的數據或事件處理程序(以便以后可以重新添加它們),請改用 .detach() 。

在我看來,在你的情況下可以只構造字符串,它是所有<option>元素的串聯。 然后您可以使用jQuery.html將所有舊選項替換為新選項。 您不僅可以解決您的主要問題,而且還具有一些性能優勢。 您應該了解的問題是,如果您更改頁面上的某些元素,Web 瀏覽器必須重新計算頁面上所有現有元素的位置或樣式。 因此,如果您在循環中調用jQuery.append ,那么每次調用都會至少跟隨回流,這是擴展性的。 所以你應該更好地編寫你的程序,以便減少頁面上的更改次數。 如果您首先將<select>元素的innerHTML構造為 HTML 字符串並使用一次jQuery.html調用(或僅設置 DOM 元素的innerHTML屬性),您將獲得性能改進。

我在您的程序中看到的另一個問題是初始化“項目”和“任務”中的選擇。 如果用戶開始編輯該行,則選擇元素將填充dataUrl: 'Timesheet/TaskList'dataUrl: 'Timesheet/ProjectList' 因此,您將擁有所有項目和任務,而不僅僅是'Customer'的項目以及基於'Customer''Project'值的任務。 我認為您必須在開始編輯之前設置dataUrl行相關初始值 例如,在表單編輯的情況下,您可以在onInitializeForm回調中執行此操作。 如果您使用內聯編輯,您應該調用editRow之前執行相同的editRow

我建議您仔細檢查答案的演示代碼。 它不使用dataUrl但多次更改value屬性。 在您的情況下,更改value屬性將對應dataUrl的設置。

好的,問題是在 ondblClickRow 事件處理程序中我設置了 editoptions / dataUrl 屬性。 因為此時我還沒有指定 editoptions / dataEvents 屬性,所以它基本上是什么都不覆蓋靜態事件處理程序。

在 ondblClickRow 事件處理程序中,我只覆蓋了 Project 和 Tasks 下拉菜單,這解釋了為什么刪除了 Project 處理程序而不是 Customer 處理程序。

向 Oleg 道歉:一開始我沒有發布完整的代碼,所以我沒有包含雙擊事件。

無論如何,Oleg 如果您能建議我如何保留事件處理程序,我可以給您答案。 否則,即使您的幫助非常寶貴,我也會將此作為答案。 我猜我可能需要將事件處理程序定義移到 dblclick 事件處理程序而不是列定義中?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM