Search code examples
javascriptsweetalert2

Display loading sweet alert dialog while waiting ajax finnish


I'm using https://sweetalert2.github.io/

I tried using one single sweet dialog, but due to the others I couldn't make it work, and i've seen examples with fetch, but I'm using ajax, I saw a example with nested dialogs but once again, with fetch. In the code I put there are 2 comments where I would like to handle the loading dialog.

This is my script:

$(document).on("submit", "#formNuevoEstudiante", function (event) {
  event.preventDefault();
  $("#btnSubmit").prop("disabled", true);
  let ap_paterno = $("#ap_paterno").val();
  let ap_materno = $("#ap_materno").val();
  let nombre = $("#nombre").val();
  let sexo = $("#sexo option:selected").val();
  let no_control = $("#no_control").val();
  let carrera = $("#carrera option:selected").val();
  let semestre = $("#semestre option:selected").val();

  let sexo2 = sexo == "F" ? "Femenino" : "Masculino";
  let mensaje = `x`;
  let mensaje2 = `x`;
  //Here is where I wan't to integrate the loading dialog
  $.ajax({
    url: "utils/ajax/nuevo_estudiante.php",
    method: "POST",
    data: {
      ap_paterno: ap_paterno,
      ap_materno: ap_materno,
      nombre: nombre,
      sexo: sexo,
      no_control: no_control,
      carrera: carrera,
      semestre: semestre,
    },
    success: function (resp) {
      if (resp == "existe") {
        Swal.fire({
          title: "Ya se encuentra registrado",
          text: "x",
          icon: "warning",
          confirmButtonText: "Aceptar",
          confirmButtonColor: "#0275D8",
        }).then(function () {
          window.location.href = "index2.php";
        });
      } else if (resp == "error") {
        Swal.fire({
          title: "Error",
          text: "x",
          icon: "error",
          confirmButtonText: "Aceptar",
          confirmButtonColor: "#0275D8",
        });
      } else if (resp == "ok") {
        //Here is where I wan't to close the loading dialog
        Swal.fire({
          title: "Registro exitoso",
          html: "<pre>" + mensaje + "</pre>" + mensaje2,
          icon: "success",
          confirmButtonText: "Aceptar",
          confirmButtonColor: "#0275D8",
        }).then(function () {
          window.location.href = "index2.php";
        });
      }
    },
  });
});

Solution

  • The example given in the SWAL2 website isn't very suited for your use as it creates an input form itself while you already have an HTML form that gets input from the user. A basic easy-to-implement solution would be to use the showLoading and hideLoading methods with what you already have. From the documentation :

    Swal.showLoading(): Shows loader (spinner), this is useful with AJAX requests. By default the loader be shown instead of the "Confirm" button, but if you want another button to be replaced with a loader, just pass it like this: Swal.showLoading(Swal.getDenyButton())

    Swal.hideLoading(): Hides loader and shows back the button which was hidden by .showLoading()

    Just after the event.preventDefault(); line, you can add a loading dialog that will just display a loading message:

    Swal.fire({
      title: "Loading...",
      html: "Please wait a moment"
    })
    Swal.showLoading()
    

    Then, at the beginning of the success callback of your ajax request, just before entering the if condition, simply add a Swal.hideLoading() to stop displaying the loading animation.

    Why does hideLoading and showLoading work on an already displayed popup?

    The reason is because SweetAlert2 kind of (it seems to work like that but I didn't confirm it) works using static methods which takes their execution to a "global" scope, meaning that when you call one of SweetAlert2 methods, it runs and stores data in the same place: the Swal class which is shared everywhere. (If you want to know more about static class, there are several articles you can read on the internet)

    Disclaimer! Now, I didn't take a look at how Swal stores data, or how it handles everything, but for the sake of argument, let's say it stores inside static properties like currentTitle, isLoading (which dictates whether or not a loading animation should be added to the popup), and more. That is effectively one reason why there's only one popup displayed at a given time (although by definition, there should be only one displayed).

    So, when you call Swal.fire(), it essentially updates the Swal class properties (setting the currentTitle to Hello for example). When you call it again, it updates it again and effectively overwrites the values set by the previous call of fire(), replacing them with new ones.

    But, unlike fire() which completely overwrites every property for the currently displayed popup, hideLoading and showLoading methods only overwrite ONE property: isLoading (reminder: this is how we've postulated SweetAlert works, the implementation could be made otherwise but for simplicity's sake, we assume it's like that) and let the others as is. That is why, when you use fire(), a new popup is displayed, but when using hideLoading and showLoading, the current popup displayed is changed.