0

I have a function that asks users for confirmation when selecting a value from a Select dropdown. When using the regular JavaScript confirm(), the change event does not get the newly selected value without clicking on confirm. This can be seen in this Fiddle.

When a value is selected, and the user clicks cancel, the same value is shown in an alert dialog. When the user clicks confirm, the newly selected value is displayed.

However, I'd like to use SweetAlert. When changing the value with SweetAlert, the change happens without even selecting confirm or cancel. As demonstrated in this Fiddle. When a value is selected, an alert dialog is displayed right after selection, unlike with the pure JS Confirm() which blocks the event somehow.

I'd like to achieve the same effect as the JS confirm(), where the change event is not triggered while the user has not clicked confirm or cancel, when using SweetAlert.

Aside from both Fiddles which demonstrate the problem, here's the code I'm using:

Some simple HTML select:

<select id="dropdownId">
    <option value="volvo">Volvo</option>
    <option value="saab">Saab</option>
    <option value="mercedes">Mercedes</option>
    <option value="audi">Audi</option>
</select>

The JavaScript confirm() version (which does what it needs to do):

var prev_val;
$('#dropdownId').focus(function () {
    prev_val = $(this).val();
}).change(function (e) {
    var select = this;
    $(this).blur();

    var success = confirm('Are you sure you want to change the Dropdown?');
    if (success) {
        // Other changed code would be here...
    } else {
        $(this).val(prev_val);
        return false;
    }
});

$('#dropdownId').change(function (e) {
    alert($(this).val());
});

And the SweetAlert version, where the change event should wait on the response of the SweetAlert dialog.

var prev_val;
$('#dropdownId').focus(function () {
    prev_val = $(this).val();
}).change(function (e) {
    var select = this;
    $(this).blur();

    return swal({
        title: "Are you sure?",
        text: "Change dropdown select?",
        type: "warning",
        showCancelButton: true,
        confirmButtonText: "Yes!",
        cancelButtonText: "No!",
        closeOnConfirm: true,
        closeOnCancel: true
    },
    function (isConfirm) {
        if (isConfirm) {
            return true;
        } else {
            $(select).val(prev_val);
            return false;
        }
    });
});

$('#dropdownId').change(function (e) {
    alert($(this).val());
});

Edit:

Moving the logic to the confirm handler of the dialog does not solve this issue. I'm using a framework (Apache Tapestry) which listens for a change event on the select. When using the solution as RRR stated, in this fiddle, the change event still happens. Which still causes it to fire an event to my backend, unlike with the JS confirm() which does not change the value until confirm was clicked.

Edit 2:

My problem doesn't really seem to be that clear. Here are the steps I undertake to try and show what the root of the problem is:

When using the JS confirm from this fiddle. The following happens:

  1. I click on a value
  2. It asks for confirmation
  3. On confirm, it logs the new value. On cancel, it logs the original value.

When using the SweetAlert dialog, using this fiddle. The following happens:

  1. I click on a value
  2. It logs the newly selected value, before confirming/cancelling
  3. On confirm/cancel I can execute logic.

When using the SweetAlert dialog, as edited by RRR in this fiddle. The following happens:

  1. I click on a value
  2. It logs the newly selected value, before confirming/cancelling
  3. On confirm/cancel, it shows an alert

Both my and RRR's SweetAlert example have the same issue. Namely, step 2. Not the fact that it logs, but the fact that the value actually changes. Unlike in the first pure JS example, where the value does NOT change unless confirm is clicked.

erikvimz
  • 5,256
  • 6
  • 44
  • 60
Jaims
  • 1,515
  • 2
  • 17
  • 30
  • I have updated your fiddle kindly check https://jsfiddle.net/oLncxb96/1/ – RRR May 30 '16 at 07:00
  • @RRR Thank you, but the problem is that the change event still happens. I'm using a framework that emits an event to the backend when a change event happens. In your edited case, the change *still* happens, but is just commented out. I should have added that in my question. My mistake – Jaims May 30 '16 at 07:05
  • You call swal onchange! The event is then already triggered! Same for your js version using `confirm()`. The event WAS already triggered. I don't get what you want to achieve. – Louys Patrice Bessette May 30 '16 at 07:10
  • @LouysPatriceBessette I don't want the change event to have the newly selected value without confirming. As seen in the first `Fiddle`, when you select a value and cancel, the original value is shown. When you select a value and confirm, the new value is shown. With the second `Fiddle`, if you select a value, the selected value is shown without having to confirm. The JS confirm shows the **correct** value at every time, unlike the `SweetAlert` version. – Jaims May 30 '16 at 07:15
  • Well... Did you compared the behavior of [`confirm()` fiddle](https://jsfiddle.net/qL6amd3x/) and [`swal()` fiddle updated by RRR](https://jsfiddle.net/oLncxb96/1/) ??? Looks no problem to me. – Louys Patrice Bessette May 30 '16 at 07:23
  • @LouysPatriceBessette The problem with that is that the value actually still does change. If you remove the comment which displays the value, the newly selected value (without confirming) is still displayed. I don't need to move my logic to another handler, I just want it to have the same functionality as a regular `alert`. Which does **not** change the value without confirming. Maybe `SweetAlert` just isn't capable of this. – Jaims May 30 '16 at 07:29
  • @Jaims as the function itself says `change()` it gets triggered only when the value of `select` changes... so you cant actually fire the code inside `change` if you detach the event :) – RRR May 30 '16 at 07:30
  • Okay... I now see a difference. When answer is no with swal, you don't get the alert.. It's the only diff. – Louys Patrice Bessette May 30 '16 at 07:31
  • @Jaims yes SweetAlert is just a replication of browser's dialog box which doesnt exactly work like default browser dialog box – RRR May 30 '16 at 07:32
  • if you need an alert on either cases then kindly check https://jsfiddle.net/oLncxb96/2/ – RRR May 30 '16 at 07:34
  • In your code, you rely on the `change` event (an OCCURED change event) to trigger either `confirm()` or `swal()`. I still don't get the question. – Louys Patrice Bessette May 30 '16 at 07:39
  • Pure js cannot do what u want,but can make code look very like it.Use Promise,or Use await&async(ES6) – gu mingfeng May 30 '16 at 07:39
  • Arrrg... Saw your 2nd edit. Did you try to just remove the `return` in front of `swal({` ? – Louys Patrice Bessette May 30 '16 at 07:51
  • @gumingfeng I'll look into that. Thank you. – Jaims May 30 '16 at 07:58
  • @LouysPatriceBessette I have, the same problem remains. – Jaims May 30 '16 at 07:58
  • Still on it. I think I have your issue. I'm editing. – Louys Patrice Bessette May 30 '16 at 08:44

2 Answers2

1

Ok. Here is the issue.

You call 2 different actions at onchange event:
1- The big function...
2- A test alert.

Both occur at the same time. <-- Here lies the confusion!

This is why it appeared to you that swal doesn't "wait" to get an answer from the user.

Try this... And look at your console.log messages:

var prev_val;

$('#dropdownId').focus(function () {
    prev_val = $(this).val();
    console.log("On focus event value : "+prev_val);    // ADDED
    }).change(function (e) {

        var select = this;
        console.log("At the BEGINNING of the change event : "+$(select).val()); // ADDED
        $(this).blur();

        swal({  // REMOVED return in front of it
            title: "Are you sure?",
            text: "Change dropdown select?",
            type: "warning",
            showCancelButton: true,
            confirmButtonText: "Yes!",
            cancelButtonText: "No!",
            closeOnConfirm: true,   // These are default.. useless to specify
            closeOnCancel: true     // These are default.. useless to specify
        },
        function (isConfirm) {
            if (isConfirm) {
                //return true;  // no need to return anything - commented out
                console.log("swal YES");
                console.log("At the END of the change event : "+$(select).val());
            } else {
                $(select).val(prev_val);
                //return false; // no need to return anything - commented out
                console.log("swal NO");
                console.log("At the END of the change event : "+$(select).val());
            }
            // Here is a callback final test alert!
            alert("Callback alert: "+$(select).val());
        });
    });

/*$('#dropdownId').change(function (e) {    // This was a bad idea ! ;)
    alert($(this).val());
});*/
Louys Patrice Bessette
  • 33,375
  • 6
  • 36
  • 64
  • Thank you for the answer, I appreciate the help. And indeed, both functions happening at the same time is where the problem lies. But when using a regular JS `confirm`, they do **not** happen at the same time. As if everything is paused (including the second change event) until an action (confirm/cancel) has taken place. `SweetAlert` does not pause anything, causing it to continue. That's the problem, but sadly not the solution. I'd like it to pause and not call the change event, just like with the JS confirm. If you remove the comment tags, you'll see the change *still* takes place. – Jaims May 30 '16 at 09:21
  • You are calling function `swal()` from within an event handler. Have to let it time to execute! *MAYBE* `alert()` breaks the event triggered functions... I don't know. STILL ! As I said before, your `change` event was triggered BEFORE ANYTHING happens here... In fact, this IS what triggers your script --> For both solutions. So I don't get your actual need. – Louys Patrice Bessette May 30 '16 at 09:33
  • Most likely, the issue is the following: `confirm()` seems to pause all JavaScript. Most likely by pausing threads and whatnot. `SweetAlert` does its job asynchronously, therefore not stopping any other events (read: change event) from happening. Causing the side effects which I require. I'll handle this in another way, but I'll give you a +1 for the effort and helpful tips! – Jaims May 30 '16 at 10:24
  • A sleep later... I found [this answer](http://stackoverflow.com/a/550583/2159528) that may interest you. – Louys Patrice Bessette May 30 '16 at 17:53
0

In my case sweet alert 2 was blocking my binded event handlers:

    Swal.fire( // Not works - Nothing will happen onclick
      {html: `<button id="btn1" onclick="alert('clicked')">Delete</button>`,
    )

So i binded the event handlers in javascript instead, on modal open:

    Swal.fire(
      {html: `<button id="btn1">Delete</button>`,
      onOpen: () => {document.querySelector('#btn1').onclick = () => {alert('clicked')}
    )
yaya
  • 7,675
  • 1
  • 39
  • 38