Перед продолжением покажите Bootstrap Modal - PullRequest
0 голосов
/ 14 июля 2020

Итак, у меня проблема с кодом в JS, продолжающимся перед отображением моего Bootstrap Modal.

Этот сайт предложит пользователю ввести информацию, и после того, как вся информация будет введена, пользователь нажимает кнопку «Сохранить», которая выполняет функцию «passTimeToSpring ()».

Когда эта кнопка нажата, я хочу, чтобы отображалось модальное окно, чтобы пользователь не подумал, что сайт просто завис, но проблема у меня m, если код выполняется сначала перед отображением модального окна. Я предполагаю, что это связано с тем, что модальный (при вызове) выполняется асинхронно в другом потоке?

Я впервые заметил это, когда у меня был запущен следующий код:

Модальный код:

<div class="modal fade" id="pleaseWaitModal" tabindex="-1" role="dialog" aria-labelledby="ModalCenterTitle" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Please Wait...</h5>
            </div>
            <div class="modal-body">
                <p>The information is currently being processed. Please Wait :)</p>
            </div>
        </div>
    </div>
</div>

JS Код:

function passTimeToSpring() {
    $('#pleaseWaitModal').modal({show: true});
    alert(true);
    
    /* data collection stuff and POST */
}

Кнопка «Сохранить» HTML:

<button class="btn btn-primary btn-lg btn-block" data-toggle="tooltip" data-bs-tooltip="" type="button" title="Fill all days before saving." onclick="passTimeToSpring()">Save All Time Entries</button>

Когда я заметил, что предупреждение появилось до того, как появилось модальное окно, я понял это вероятно, это проблема asyn c, однако я новичок в материалах JS asyn c. Я нашел это решение Значение ожидания в bootstrap подтвердить модальное? , что побудило меня попробовать этот код

const modal = new Promise(function(resolve, reject){
    $('#pleaseWaitModal').modal({show: true});
    resolve(true);
  }).then(function(val){
    //val is your returned value. argument called with resolve.
    alert(val);
  }).catch(function(err){
    //failure
  });

var test = await modal;

, похоже, это все еще не сработало. Пожалуйста помоги? :) спасибо

Ответы [ 3 ]

1 голос
/ 15 июля 2020

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

Правильным решением является независимая обработка «заблокированного» состояния и обработка показа / скрытия "пожалуйста, подождите ..." модальное окно как дополнительная возможность функции блокировки. Хорошая реализация такой функции должна позволять блокировку / разблокировку с отображением модального окна «пожалуйста, подождите» или без него.

Вот упрощенный принцип:

let pageLocked = false;

function toggleLockedState(state) {
  pageLocked  = state;

  // a basic example would look like this:
  $('body').toggleClass('isLocked', state);
  $('#pleaseWaitModal').modal(state ? 'show' : 'hide' );
}

function pageLockingFunction() {
  // lock page
  toggleLockedState(true);
  $.get( "your/get/url/here", function( data ) {
    // do something with data
    console.log(data);
    // unlock page
    toggleLockedState(false);
  });
}

Преимущество этого подхода в что любая другая функция может запросить текущее значение pageLocked и, при необходимости, выйти или войти в заблокированное состояние. Кроме того, вышеизложенное упрощено. В реальной жизни управление состоянием приложения должно осуществляться специальным модулем / классом, который также предоставляет методы для прослушивания и реагирования на изменения состояния.

Возвращаясь к примеру, базовый c способ блокировки / разблокировки страница должна была бы добавить / удалить класс к элементу <body> (isLocked выше), применяя pointer-events: none ко всем элементам на странице - таким образом, отключая взаимодействия.

Помимо обработки блокировки страницы, ваша функция отображает / скрывает модальное окно загрузки, объясняя пользователям, что происходит (почему страница заблокирована).

В идеале, модальное окно также должно содержать кнопку «отменить загрузку», которая должна выйти из заблокированного состояния, чтобы они могли, для Например, попробуйте еще раз, если что-то пошло не так. Не забудьте установить pointer-events: all на кнопку отмены, чтобы пользователь мог взаимодействовать с ней, даже когда страница заблокирована.

Если вы хотите что-то сделать с данными после их загрузки, верните сам вызов из pageLockingFunction и верните data внутри возвращенного вызова:

function pageLockingFunction() {
  toggleLockedState(true);
  return $.get( "your/get/url/here", function( data ) {
    toggleLockedState(false);
    return data;
  });
}

и используйте его так :

pageLockingFunction().then(data => {
  console.log('closing #pleaseWaitModal...');
  console.log(data);
}
0 голосов
/ 15 июля 2020

В моем исходном сообщении я пытался sh код показать Modal в отдельном потоке и продолжить тяжелую работу в основном потоке. Я решил обработать событие, которое фактически вызывало задержку в веб-воркере (отдельный поток).

Эта программа использует Java серверную часть Spring, поэтому собранные мной данные отправляются в Spring, что в свою очередь вставляет информацию в базу данных. Именно этот процесс вызывает задержку, так как ответ браузеру не возвращается до тех пор, пока команда вставки не будет завершена.

После выполнения этой команды страница затем переходит к GET, потому что refre sh просто снова отправил бы POST.

Вот мои последние образцы кода

timeSubmissionWorker:

onmessage = function(e) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "/url", false);
    xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
    xhr.addEventListener("loadend", function (e) {
        console.log(e);
        postMessage({result: true});
    });
    xhr.send(JSON.stringify(e.data));
};

main html file:

function passTimeToSpring() {
    $('#pleaseWaitModal').modal({show: true});
    
    var myWorker = new Worker("timeSubmissionWorker.js");
    myWorker.postMessage(*data*);

    myWorker.onmessage = function(e) {
        //reloads the page after the information has posted.
        window.location.href = "/url";
    }
}
0 голосов
/ 14 июля 2020

Я думаю, ваша функция «passTimeToSping ()» должна быть объявлена ​​как «() => passTimeToSpring ()», чтобы HTML не выполнялась до щелчка

<button class="btn btn-primary btn-lg btn-block" data-toggle="tooltip" data-bs-tooltip="" type="button" title="Fill all days before saving." onclick="() => passTimeToSpring">Save All Time Entries</button>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...