Creating a ‘blocking’ confirm dialog with dojo

Update 30.03.2018: Version 1.10 of dojotoolkit includes a dijit/DialogConfirm now, which is simply a dijit/Dialog featuring ‘OK’ and ‘Cancel’ buttons, no blocking though.

Update 15.10.2012: Code is available on githup now. I also fixed updating the content of the dialog after creation (e.g. dialog.set(‘content’, newContent) overwrote the confirm/cancel buttons because they were part of the content.

Update 03.12.2011: I updated the code to use dojo 1.7 with AMD. I also moved the creation of the Deferred to the show() method as suggested by ben, which will make the instance of the dialog reusable. Added new property hasUnderlay: true, which can be set to false.

JavaScript has a window.confirm() method, which opens a dialog and stops code execution until the user presses either the ‘OK’ or ‘Cancel’ button. Dojo also comes with a dijit.Dialog widget, but that doesn’t exhibit the same blocking behavior. Since I needed to simulate the native blocking behavior for an application I am currently developing, I extended the widget and created the DialogConfirm widget with the following features:

  • shows an ‘OK’ and ‘Cancel’ button by default (can be set to false)
  • shows a check box, which when set will remember the decision and not ask again (can be set to false)
  • the show() method returns a dojo.Deferred() which allows you to simulate the code blocking
  • underlay can be hidden

The demo of the DialogConfirm widget shows you how to halt code execution by just using the then() method of the returned deferred as follows:

var dialog = new snet.DialogConfirm({
   title: 'Confirm',
   content: '<p>Dialog content lore ipsum</p>'
});
dialog.show().then(function(remember) {
   // user pressed ok button
   // remember is true, when user wants you to remember his decision (user ticked the check box)
   if (remember) {
      // do something and never show this dialog again
   }
   else {
      // do something
   }
}, function() {
   // user pressed cancel button
   // do something
});

Join the Conversation

22 Comments

Leave a Reply to Simon Cancel reply

Your email address will not be published. Required fields are marked *

  1. I put the below code in js.And I added Dialogconfirm.js as the plugin in my application.when I debug in the js file it shows “DialogConfirm is undefined”.Could you please suggest me how to call the show method in js.

    var dialog = new DialogConfirm({
       title: 'Confirm',
       content: 'Dialog content lore ipsum'
    });
    dialog.show().then(function(remember) {
       // user pressed ok button
       // remember is true, when user wants you to remember his decision (user ticked the check box)
       if (remember) {
          // do something and never show this dialog again
       }
       else {
          // do something
       }
    }, function() {
       // user pressed cancel button
       // do something
    });
    

    Note:
    I am using dojo version 1.7 in my application.

    1. Without seeing your code I can’t tell. You have to use require to load the module. First thing is to check if DialogConfirm.js is really loaded (open Network panel in Developer Tools, press F12 in Firefox) and passed as an argument. As long as it is undefined something is wrong.

      Look at the source code of the demo at https://www.speich.net/articles/dojo-confirmdialog.php for how to load this module or see comments below.

  2. Hi Simon,

    If you happen to have code compliant with Dojo 1.6 lying around, it would be greatly appreciated if you could post that too. Stuck to 1.6 🙁 and having hard time getting it to work there.

    Thanks!

    Bas

    1. Unfortunately, I don’t have it anymore (should have moved code to Github), but I guess all you have to do is replace define() with dojo.provide(), since the dialog does not use any dojo 1.7 stuff other than the AMD loader IIRC.

  3. Hi Simon,

    I’m new in dojo. I used your code in last version 1.6 and it worked ok.
    But now within version 1.7 it dont find the file.

    The dir structure Im using is:
    dojo
    -> digit

    -> dojo

    -> dojox

    -> snet
    -> DialogConfirm

    Dojo search into dojo->dojo directory, and I dont want to put there the snet directory.

    1. Sorry, but without seeing you code I can’t tell you exactly what to do. But have a look at the dojoConfig in the source of the demo page. You can put the DialogCofirm.js anywhere you like and you don’t need the snet at all. That’s just to map the:
      var dialog = new snet.DialogConfirm({}) and the require([snet/DialogConfirm]
      to:
      /library/speich.net/DialogConfirm.js
      by using:

      var dojoConfig = {
      	...
      	packages: [{
      		... 
      		{'name': 'snet', 'location': '/library/speich.net' }
      	]
      };

      You will also have to change the declare(‘snet.DialogConfirm’) in DialogConfirm.js

      1. Thanks Simon,

        it works now ok…, except for one thing:
        only when async:true gives the next error:
        Could not load class ‘dijit.MenuItem

        Do you know how to fix it ?

  4. hi simon,

    I had a look at the sample, but being a bit new to the constucts of js , can you show how I can replace
    function ConfirmMultipleSign()
    {
    var x = window.confirm(“Do you want to sign another page?”);
    if(x){
    document.getElementById(“MultipleSignFlag”).value = “true”;
    }
    else{
    document.getElementById(“MultipleSignFlag”).value = “false”;
    }
    }

    with you code ?

    I basically have some redirect code that executes based on the values, if false goes to google if true goes back to my url

    1. The code below does the trick:

      function ConfirmMultipleSign() {
      	var dialog = new snet.DialogConfirm({
      		title: 'Confirm',
      		duration: 500,
      		hasSkipCheckBox: false,
      		content: 'Do you want to sign another page?'
      	});
      	dialog.show().then(function() {
      		// ok button go to google
      		//dojo.byId('MultipleSignFlag').value = true;	// you probably won't need this anymore
      		window.location.href = 'http://www.google.com';
      	}, function() {
      		// cancel button, go back to your page
      		//dojo.byId('MultipleSignFlag').value = false;	// you probably won't need this anymore
      		window.location.href = 'http://www.yoursite.com';
      	});
      }
      1. Hi thanks for your reply,

        The thing is that my code,

        var x = window.confirm(“Do you want to sign another page?”);

        halts the execution of the code

        basically the redirect is to the SAME jsp page, after some server side operations.
        so,that is why i set those flags for rediect. Comeback to the page false, ok go to google
        or predefined url,true ok need to to the same operations on the same page and as the
        user again if he wants to do it again.

        the code you mentioned allows the background or the next function to execute after the mentioned duration ??? but the window.confirm does not…

        I need to set that flag

        function CallpreSign()
        {
        ConfirmMultipleSign1();
        preSign();
        //ConfirmMultipleSign();
        }

        function ConfirmMultipleSign1() {

        var x = window.confirm(“Do you want to sign another page?”);
        if(x){
        document.getElementById(“MultipleSignFlag”).value = “true”;
        }
        else{
        document.getElementById(“MultipleSignFlag”).value = “false”;
        }

        }

        any advice in dojo?

        1. Have you actually tried the code? The code is halted as in window.confirm until the user either clicks the ok button (first function is executed) or cancel button (second function is executed). The duration property only means the fade animation takes 500 milliseconds.

          1. off course i tried the code,but there was something that was getting executed in the back ground, so I was also under the impression that duration was some kind of timeout…

            but now I managed to get a working solution

            function ConfirmMultipleSign() {
            var dialog = new snet.DialogConfirm({
            title: ‘Confirm’,
            duration: 500,
            hasSkipCheckBox: false,
            content: ‘Do you want to sign another page?’
            });
            dialog.show().then(function() {
            alert(“YES”);
            preSign();
            // ok button go to google
            dojo.byId(‘MultipleSignFlag’).value = true; // you probably won’t need this anymore
            //window.location.href = ‘http://www.google.com’;

            }, function() {
            alert(“NO”);
            preSign();
            // cancel button, go back to your page
            dojo.byId(‘MultipleSignFlag’).value = false; // you probably won’t need this anymore
            //window.location.href = ‘http://www.yoursite.com’;

            });
            }

            function CallpreSign()
            {
            ConfirmMultipleSign();
            //preSign();
            //ConfirmMultipleSign();
            }
            i guess it may have been a programming sequnce that allowed the skip
            …. have to test further , but looks good !!!

          2. i wonder if the last comment got eaten…

            any way the below seem to do the job for me….

            function ConfirmMultipleSign() {
            var dialog = new snet.DialogConfirm({
            title: ‘Confirm’,
            duration: 500,
            hasSkipCheckBox: false,
            content: ‘Do you want to sign another page?’
            });
            dialog.show().then(function() {
            alert(“YES”);
            preSign();
            // ok button go to google
            dojo.byId(‘MultipleSignFlag’).value = true; // you probably won’t need this anymore
            //window.location.href = ‘http://www.google.com’;

            }, function() {
            alert(“NO”);
            preSign();
            // cancel button, go back to your page
            dojo.byId(‘MultipleSignFlag’).value = false; // you probably won’t need this anymore
            //window.location.href = ‘http://www.yoursite.com’;

            });
            }

            function CallpreSign()
            {
            ConfirmMultipleSign();
            //preSign();
            //ConfirmMultipleSign();
            }

            the last time i guess it was a mistake in program execution sequnce that allowed the code to execute in the background…

  5. it looks like the way you currently have the code, you only have 1 Deferred per instance of the dialog. this means that you can’t reuse the dialog because a Deferred can only be resolved once. you might want to consider rather than creating a Deferred once in the constructor, create a new Deferred each time in the show method. this will make it so that you can reuse the same instance of the dialog.

    1. Thank’s ben for your valuable feedback. I will do that, but this will need some other changes too, since the dialog gets automatically destroyed after the user clicks ‘OK’ or ‘Cancel’.