1

Oleg と多くの Web サイトの助けを借りて、jqGrid でカスケード データ バインド ドロップダウンを機能させることに取り組んできました。

3 つのドロップダウンがあります: 顧客 > プロジェクト > タスク。顧客を変更すると、その顧客プロジェクトでプロジェクトをリロードする必要があります。プロジェクトを変更すると、そのプロジェクト タスクでタスクをリロードする必要があります。

私は実際に、Customer で変更イベント ハンドラーを作成することにより、Project にその Customers タスクをリロードさせました。このハンドラーはgetJsonURL に対して呼び出しを行い、Project ドロップダウンの内容を新しいオプションに置き換えます。それはうまくいきます。

次に、これと同じロジックを Project ドロップダウンに適用しましたが、Project イベントが発生していないように見えます。プロジェクトのドロップダウンを変更すると、次のことがわかりました。

  1. タスクのドロップダウンは変更されません
  2. getJSONTask Json コントローラー イベントは呼び出されません (プロジェクト変更イベントで呼び出されることを意図しています)。
  3. Firebug では、Network モニターで、Task Json コントローラー イベントへの呼び出しと応答が表示されません。
  4. Firebug では、プロジェクトの変更イベント ハンドラで設定したブレークポイントにヒットしません。

ただし、Customer イベント ハンドラーは完全に機能し、Customer を変更すると、上記の 4 つのポイントがすべて期待どおりに実行されます。

プロジェクトのドロップダウンに対して変更イベントが発生していないことは確かです。

Web ページを実行し、最初のアクションとして Project ドロップダウン値を編集および変更すると、プロジェクト イベント ハンドラーが起動されないため、Project イベント ハンドラーをリセットする Customer イベントではないと思います。

それで、私の顧客変更イベント呼び出されたのに、私のプロジェクトが呼び出されなかった理由を誰かが知っていますか?

DOM などを調べて、実行時にイベントが添付されているかどうかを確認する方法はありますか? それはそれが動作する方法ですか?

jqGrid 4.4.1 を使用しています

私のjqGridはこのように設定されています:

  • インライン編集を使用
  • クリックして選択 dblclick して編集
  • 日付ピッカーが日付列に添付されています
  • 編集時に、非表示のフィールドから select db キーの値を取得しますが、それを削除できることを望んでいます。
  • 隣り合って3つの選択があります

これが私の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 () {

固定コードはこちら

change イベント ハンドラーの定義を、列の定義から 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 () {
4

2 に答える 2

2

あなたが抱えている問題の理由は、の使用法にあると思いますjQuery.empty(行と行eTask.empty();を参照eProject.empty();)。jQuery.emptyの説明を調べると、次のことがわかります。

メモリ リークを回避するために、jQuery は要素自体を削除する前に、子要素からデータやイベント ハンドラーなどの他の構成要素を削除します。

データやイベント ハンドラーを破棄せずに要素を削除する (後で再追加できるようにする) 場合は、代わりに .detach() を使用します。

<option>あなたの場合、すべての要素を連結した文字列を構築できるように思えます。jQuery.html次に、すべての古いオプションを新しいオプションに置き換えるために使用できます。主な問題を解決できるだけでなく、パフォーマンス上の利点も得られます。ページ上の要素を変更すると、Web ブラウザはページ上の既存のすべての要素の位置またはスタイルを再計算する必要があることを理解しておく必要があります。したがってjQuery.append、ループ内で呼び出すと、すべての呼び出しが少なくともリフローに続き、これは拡張的です。そのため、ページ上の変更の数が減るようにプログラムを作成する必要があります。innerHTML最初に<select>要素の を HTML 文字列として構築し、の1 回の呼び出しを使用する場合jQuery.html(またはinnerHTMLDOM 要素のプロパティのみを設定) すると、パフォーマンスが向上します。

あなたのプログラムで見られるもう 1 つの問題は、'Project' と 'Task' からの選択の初期化です。ユーザーが行の編集を開始すると、選択要素は と で埋められdataUrl: 'Timesheet/TaskList'ますdataUrl: 'Timesheet/ProjectList'。したがって、との値に基づく とのプロジェクトだけでなく、すべてのプロジェクトとタスクがあります。編集を開始する前に、行依存の初期値を設定する必要があると思います。フォーム編集の場合、たとえばコールバック内でこれを行うことができます。インライン編集を使用する場合は、を呼び出すに同じことを行う必要があります。'Customer''Customer''Project'dataUrlonInitializeFormeditRow

answerからデモのコードを注意深く調べることをお勧めします。no を使用しますが、プロパティを複数回変更します。プロパティの変更はの設定で対応します。dataUrlvaluevaluedataUrl

于 2012-11-11T15:14:47.673 に答える
0

OK、問題は、ondblClickRowイベントハンドラーでeditoptions/dataUrlプロパティを設定していたことでした。この時点ではeditoptions/dataEventsプロパティも指定していなかったため、基本的に静的イベントハンドラーを何も上書きしていませんでした。

ondblClickRowイベントハンドラーでは、プロジェクトとタスクのドロップダウンのみを上書きしていました。これは、プロジェクトハンドラーが削除され、カスタマーハンドラーが削除されなかった理由を説明しています。

オレグへの謝罪:最初に完全なコードを投稿しなかったので、ダブルクリックイベントを含めませんでした。

とにかく、オレグは、イベントハンドラーを保持する方法を提案できれば、答えを与えることができます。そうでなければ、あなたの助けがかけがえのないものであったとしても、私はこれを答えとして授与します。イベントハンドラー定義を列定義ではなくdblclickイベントハンドラーに移動する必要があるかもしれないと思いますか?

于 2012-11-13T10:30:50.117 に答える