14
function ValidateField(){
var bAllow= true;

    //some checking here

if (bAllow == true && apl.val().trim() == "")
{ 
    showDialog(); 
    showDialog().done(function() {
        return true; // wanna return true, but not success
    }).fail(function() {
        return false; //wanna return false, but not success
    });
    return false; //stop it to execute to next line
}
return bAllow; //success return }

function showDialog(){
var def = $.Deferred();
var modPop = '<div id="diaCom" title="Information?"><p>something something</p></div>';
$("#diaCom").remove();
$(modPop).appendTo('body');
$("#diaCom").dialog({
    resizable: false,
    draggable: false,
    height:150,
    width:300,
    modal: true,
    buttons: {
        "Ok": function() {  
            def.resolve();
            $(this).dialog("close");

        },
        "Cancel": function() {
            def.reject();
            $(this).dialog("close");

        }
    }
});

return def.promise();
}
//on click
if (validateField() == true){
        //do something
 }else{
        //do something
  }

hi everyone, any chance to return the value? I wish to return the true and false through showDialog().done() and fail for validatefield() function, but it not working as what I want, I can't assign to bAllow as I had already have a return false to hold the dialog to execute its next line, any idea? Or it is correct to do like these?

Se0ng11
  • 2,303
  • 2
  • 26
  • 45
  • You won't be able to cause the Javascript to wait for the completion of the deferred object, so there's no way to `return` later. I'm not sure how to "fix" this, but I think the way is to reorganize your code/logic – Ian Dec 07 '12 at 07:55
  • No, you can't return synchronously from an asynchronous task. Instead, pass the deferred! – Bergi Dec 07 '12 at 07:55
  • so means that i pass to another function, n use the other function to do the validate check instead of the same function? Can show me a bit of correct way of to do so? create a global variable, set it to true/fase based on the defferend, then in the another function, use the global variable to do checking, after that use the function to return true/false? I'm still new to deffered, just search through google n puzzle it out, come out something like this – Se0ng11 Dec 07 '12 at 07:58
  • I can't think of any code that can have the same checking as I want using this – Se0ng11 Dec 07 '12 at 08:41
  • Guess I give up on using Dialog to return anything, instead of return, i remove the button cancel, so a message will show out saying that need to reclick again the submit button due to some condition met, the user need to reclick the button again to submit the form – Se0ng11 Dec 07 '12 at 09:28
  • Or, you could submit it for them. `$("#theform")[0].submit();` – Kevin B Aug 27 '13 at 19:52

3 Answers3

34

Well, This can work.

Your dialog function... showDialog()

function confirmation(question) {
    var defer = $.Deferred();
    $('<div></div>')
        .html(question)
        .dialog({
            autoOpen: true,
            modal: true,
            title: 'Confirmation',
            buttons: {
                "Yes": function () {
                    defer.resolve(true); //answer
                    $(this).dialog("close");
                },
                "No": function () {
                    defer.resolve(false); //answer
                    $(this).dialog("close");
                }
            },
            close: function () {
                $(this).remove(); //removes this dialog div from DOM
            }
        });
    return defer.promise();
}

and then the code where you use the function...

function onclick(){
    var question = "Do you want to start a war?";
    confirmation(question).then(function (answer) {
        if (answer) {
            alert("this is obviously " + answer);//TRUE
        } else {
            alert("and then there is " + answer);//FALSE
        }
    });
}

This may seem wrong for most people. But there is always some situations where you just can't go without return from JQuery Dialog.

This will basically mimic the confirm() function. But with ugly code and a nice confirm box look :)

I hope this helps some people out.


**

EDIT: Bootstrap 3 Solution

**
I am now using [NakuPanda's][1] bootstrap library, It works really well. Basically the same as with JQueryUI but in the Bootstrap UI.
function bsConfirm(question) {
    var defer = $.Deferred();
    BootstrapDialog.show({
        type: BootstrapDialog.TYPE_PRIMARY,
        title: 'Confirmation',
        message: question,
        closeByBackdrop: false,
        closeByKeyboard: false,
        draggable: true,
        buttons: [{
            label: 'Yes',
            action: function (dialog) {
                defer.resolve(true);
                dialog.close();
            }
        }, {
            label: 'No',
            action: function (dialog) {
                defer.resolve(false);
                dialog.close();
            }
        }],
        close: function (dialog) {
            dialog.remove();
        }
    });
    return defer.promise();
}
function bsAlert(error, message) {
    BootstrapDialog.show({
        type: error ? BootstrapDialog.TYPE_DANGER : BootstrapDialog.TYPE_SUCCESS,
        title: error ? "Error" : "Success",
        message: message,
        closeByBackdrop: false,
        closeByKeyboard: false,
        draggable: true,
        buttons: [{
            label: 'OK',
            action: function (d) {
                d.close();
            }
        }]
    });
}

and using it (Pretty much the same way)

bsConfirm("Are you sure Bootstrap is what you wanted?").then(function (answer) {
    if (answer) {
        bsAlert("Well done! You have made the right choice");
    } else {
        bsAlert("I don't like you!");
    }
});
Pierre
  • 8,397
  • 4
  • 64
  • 80
  • 7
    I've used a similar approach many times. NB: your code will leave the configured `
    ` in the DOM - you need a `$(this).dialog('destroy').remove()` in the dialog's `close` handler.
    – Alnitak Aug 27 '13 at 19:55
  • @Pierre: Do I have to add any additional library for Deferred and promise to work ? – ChandniShah Apr 23 '14 at 04:36
  • @ChandniShah Only Jquery 1.5+ it is a built-in function. See `https://api.jquery.com/category/deferred-object/` for more info – Pierre Apr 23 '14 at 17:41
  • 1
    @Pierre : Thanks for yr help. But in my case this solution is nt working. It is not waiting till I click on yes or no button. – ChandniShah Apr 29 '14 at 05:49
  • @ChandniShah Please make sure the code you want it to continue with, is in the `function` statement part within the `confirmation("LA?").then(function(){ ... Your code here ... });` – Pierre Sep 01 '14 at 11:30
  • I tried the BootStrap Solution but still the function skips to the end and does not wait until the user responds which makes this solution pretty but useless unfortunately. – usefulBee Sep 11 '15 at 21:03
  • Got error --> Boolean.parse is not a function ! I used it without type casting and it worked. – QMaster Dec 11 '16 at 06:15
5

I have created this JSFIDDLE and changed the boolean parse because that was blowing up. Thanks, Pierre! This has saved me a lot of time.

javascript:

function confirmation(question) {
var defer = $.Deferred();
$('<div></div>')
    .html(question)
    .dialog({
        autoOpen: true,
        modal: true,
        title: 'Confirmation',
        buttons: {
            "Yes": function () {
                defer.resolve("true");//this text 'true' can be anything. But for this usage, it should be true or false.
                $(this).dialog("close");
            },
            "No": function () {
                defer.resolve("false");//this text 'false' can be anything. But for this usage, it should be true or false.
                $(this).dialog("close");
            }
        },
        close: function () {
            //$(this).remove();
            $(this).dialog('destroy').remove()
        }
    });
return defer.promise();
};

function onclick(){
var question = "Do you want to start a war?";
confirmation(question).then(function (answer) {
    console.log(answer);
    var ansbool = (String(answer) == "true");
    if(ansbool){
        alert("this is obviously " + ansbool);//TRUE
    } else {
        alert("and then there is " + ansbool);//FALSE
    }
});
}

$("#item").on('click', onclick);

HTML:

<button id="item">Hello, click me.</button>
CSQ
  • 611
  • 8
  • 7
1

why not use the reject method instaed of resolve("false"). You will then be able to pass an object as argument. Let's say you have multiple fieldsets of inputs, each one having a delete button :

 function confirmation(question,obj) {
    var defer = $.Deferred();
    $('<div></div>')
        .html(question)
        .dialog({
            autoOpen: true,
            modal: true,
            title: 'Confirmation',
            buttons: {
                "Oui": function () {
                    defer.resolve(obj);// pass the object to delete to the defer object
                    $(this).dialog("close");
                },
                "Non": function () {
                    defer.reject();//reject, no need to pass the object
                    $(this).dialog("close");
                }
            },
            close: function () {

                $(this).dialog('destroy').remove()
            }
        });
    return defer.promise();
}

$(document).on("click", ".btn-suppr",function (){// all delete buttons having a class btn-suppr

var question = "Are you sure to delete this fieldset ?";
confirmation(question,$(this)).then(function (obj) {

                                obj.parent('fieldset').remove(); // remove the parent fieldset of the delete button if confirmed

                            });
                        });
Nima Soroush
  • 12,242
  • 4
  • 52
  • 53
plancton
  • 324
  • 2
  • 5