jQuery Deferred and Dialog box
Asked Answered
S

3

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?

Shcherbakov answered 7/12, 2012 at 7:42 Comment(6)
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/logicOverwork
No, you can't return synchronously from an asynchronous task. Instead, pass the deferred!Cymric
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 thisShcherbakov
I can't think of any code that can have the same checking as I want using thisShcherbakov
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 formShcherbakov
Or, you could submit it for them. $("#theform")[0].submit();Characteristic
R
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!");
    }
});
Resplendence answered 27/8, 2013 at 19:36 Comment(7)
I've used a similar approach many times. NB: your code will leave the configured <div></div> in the DOM - you need a $(this).dialog('destroy').remove() in the dialog's close handler.Nolita
@Pierre: Do I have to add any additional library for Deferred and promise to work ?Stratify
@Stratify Only Jquery 1.5+ it is a built-in function. See https://api.jquery.com/category/deferred-object/ for more infoResplendence
@Resplendence : 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.Stratify
@Stratify 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 ... });Resplendence
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.Porphyrin
Got error --> Boolean.parse is not a function ! I used it without type casting and it worked.Gensler
A
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>
Amphoteric answered 15/8, 2014 at 21:29 Comment(0)
R
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

                            });
                        });
Radborne answered 2/12, 2014 at 15:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.