Bootstrap 模态和 Datatables.net

Bootstrap Modal and Datatables.net

我在数据表事件处理程序中显示一个 bootstrap 模态对话框,其定义如下:

   dt_table.on('click', 'tr', function(e) {
        //console.log('row clicked');
        if ( $(this).hasClass('selected') ) {
            $(this).removeClass('selected');
        }
        else {
            //check to see if user has any pending changes
            var saveButton = document.getElementById('saveBtn');
            if (saveButton && !saveButton.disabled) {
                //for now if save button is enabled ask user if they're sure they don't want to save pending changes first
                var options = {
                  'backdrop' : 'static',  //prevents clicking outside the model to dismiss dialog
                }
                $('#pendingChanges').modal(options);
                var save_pending_changes = $('#save_pending_changes').val();
                console.log(save_pending_changes);
                if (save_pending_changes) {
//                    console.log(e);
                    //e.preventDefault();
                    return;
                }
            }

            console.log('about to execute default behavior');

            //first unselect any other selected row
            dt_table.$('tr.selected').removeClass('selected');

            //then select row of interest
            $(this).addClass('selected');

            var rowIndices = dt_table.row('.selected')[0];
            selectedRowIndex = rowIndices[0];

            //set hidden param
            $('#selectedRowIndex').val(selectedRowIndex);

            var row = dt_table.rows(rowIndices);

            if (row.data().length == 0) {
                //e.preventDefault();
                return;
            }
            var id = row.data()[0]['id'];
            var url = '/report/' + id + '/';
            //window.location = url;
            $('#notes_display').load(url +  ' #notes_display');
        }
    });

我 运行 遇到的问题是整个事件处理程序在模态消失之前执行。它的行为就好像模态在它自己的线程中是 运行 一样。我该如何解决这个问题?

我的模态定义为

<div class="modal fade" id="pendingChanges" tabindex="-1" role="dialog" aria-labelledby="pendingChangesLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h3 class="modal-title" id="pendingChangesLabel">You have unsaved changes</h3>
      </div>
      <div class="modal-body">
        <p>
            <strong>Are you sure you want to leave?</strong>
        </p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal" onclick="saveChanges(true)">No</button>
        <button type="button" class="btn btn-primary" data-dismiss="modal" onclick="saveChanges(false)">Yes</button>
      </div>
    </div>
  </div>
</div>

逻辑示例会有所帮助 :) 但我想我明白了问题所在。我会建议您在 promises 中拆分工作流程:

//determine if modal should displayed
function determine(tr) {
  return new Promise(function(resolve) {
    //dont know the logic here 
    resolve(true / false)
  })
}

//show modal and return caption of the clicked button
function showModal() {
  return new Promise(function(resolve) {
    $('#pendingChanges button').one('click', function(e) {
      resolve(e.currentTarget.innerText)
    })
    $('#pendingChanges').modal({
      backdrop: 'static',
      keyboard: false
    })    
  })
}

dt_table.on('click', 'tr', function(e) {
  determine(this).then(function(result) {
    if (result) {
      showModal().then(function(button) {
        console.log(button) //Yes or No
      })
    }
  })
})

未测试,但应该没问题。

  1. determine() 是否应根据 <tr>
  2. 显示模态
  3. 调用 showModal() 仅在单击按钮时才解析
  4. 你得到 YesNo

感谢 davidkonrad 我解决了我的问题。这是工作代码。

<input type="hidden" name="save_pending_changes" id="save_pending_changes" value="false"/>
<!-- Modal -->
<div class="modal fade" id="pendingChanges" tabindex="-1" role="dialog" aria-labelledby="pendingChangesLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h3 class="modal-title" id="pendingChangesLabel">You have unsaved changes</h3>
      </div>
      <div class="modal-body">
        <p>
            <strong>Are you sure you want to leave?</strong>
        </p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal" onclick="saveChanges(true)">No</button>
        <button type="button" class="btn btn-primary" data-dismiss="modal" onclick="saveChanges(false)">Yes</button>
      </div>
    </div>
  </div>
</div>
function saveChanges(save) {
    $('#save_pending_changes').val(save);
}

dt_table.on('click', 'tr', function(e) {
    var oldRow = getCurrentRow();
    determine(this).then(function(result) {
        var enabled = result['enabled'];
        var tr = result['tr'];
        if (enabled) {
            showModal().then(function(save) {
                if (save == 'true') {
                    setSelection(oldRow);
                    return;
                }
                else {
                    select(tr);
                }
            })
        }
        else {
            select(tr);
        }
    })
})

//determine if modal should displayed
function determine(tr) {
    return new Promise(function(resolve) {
        //check to see if user has any pending changes
        var saveButton = document.getElementById('saveBtn');
        var enabled = false;
        if (saveButton) {
            enabled = !saveButton.disabled;
        }
        var result = {};
        result['enabled'] = enabled;
        result['tr'] = tr;
        resolve(result);
    })
}

//show modal and return caption of the clicked button
function showModal() {
    return new Promise(function(resolve) {
        $('#pendingChanges button').one('click', function(e) {
            var save_pending_changes = $('#save_pending_changes').val();
            resolve(save_pending_changes);
        })
        $('#pendingChanges').modal({
            backdrop: 'static',
            keyboard: false
        })
    })
}

function getCurrentRow() {
    return (dt_table.$('tr.selected'));
}

function setSelection(row) {
    //first unselect any other selected row
    dt_table.$('tr.selected').removeClass('selected');

    //then select row
    row.addClass('selected');
}

function select(tr) {
    //first unselect any other selected row
    dt_table.$('tr.selected').removeClass('selected');

    //then select row of interest
    $(tr).addClass('selected');

    var rowIndices = dt_table.row('.selected')[0];
    selectedRowIndex = rowIndices[0];

    //set hidden param
    $('#selectedRowIndex').val(selectedRowIndex);

    var row = dt_table.rows(rowIndices);

    if (row.data().length == 0) {
        //e.preventDefault();
        return;
    }
    var id = row.data()[0]['id'];
    var url = '/report/' + id + '/';
    //window.location = url;
    $('#notes_display').load(url +  ' #notes_display');

}