Bootstrap Модальные и Datatables.net - PullRequest
1 голос
/ 21 апреля 2020

Я отображаю модальное диалоговое окно bootstrap из обработчика событий datatables, который определен следующим образом:

   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>

Ответы [ 2 ]

1 голос
/ 22 апреля 2020

Благодаря Давидконрад Я решил свою проблему. Вот рабочий код.

<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');

}
1 голос
/ 22 апреля 2020

Пример логики c был бы полезен :) Но, думаю, я понимаю проблему. Я рекомендую вам разделить рабочий процесс на обещания:

//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. Вызов showModal(), который разрешается только при нажатии кнопки
  3. You получить либо Yes, либо No
...