Here is the solution I came up when I had been facing the same question. It's not completely programmatic, but using the template makes the code more readable and flexible for changes.
Better to see once than to hear 100 times, so see all the code below live at jsFiddle: http://jsfiddle.net/phusick/wkydY/
The main principle I employ is the fact that dijit.Dialog::content
may not only be a string, but also a widget instance. So I subclass dijit.Dialog
to declare ConfirmDialog
class. In ConfirmDialog::constuctor()
I declare and instantize a widget from a template and set it to be dialog's content. Then I wire onClick
actions in ConfirmDialog::postCreate()
method:
var ConfirmDialog = declare(Dialog, {
title: "Confirm",
message: "Are you sure?",
constructor: function(/*Object*/ kwArgs) {
lang.mixin(this, kwArgs);
var message = this.message;
var contentWidget = new (declare([_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], {
templateString: template, //get template via dojo loader or so
message: message
}));
contentWidget.startup();
this.content = contentWidget;
},
postCreate: function() {
this.inherited(arguments);
this.connect(this.content.cancelButton, "onClick", "onCancel");
}
})
The template markup:
<div style="width:300px;">
<div class="dijitDialogPaneContentArea">
<div data-dojo-attach-point="contentNode">
${message}
</div>
</div>
<div class="dijitDialogPaneActionBar">
<button
data-dojo-type="dijit.form.Button"
data-dojo-attach-point="submitButton"
type="submit"
>
OK
</button>
<button
data-dojo-type="dijit.form.Button"
data-dojo-attach-point="cancelButton"
>
Cancel
</button>
</div>
</div>
Now use ConfirmDialog
instead of dijit.Dialog
:
var confirmDialog = new ConfirmDialog({ message: "Your message..."});
confirmDialog.show();
Important: Do not forget to disconnect any connects to the dialogs callbacks and destroy dialog when closed.
If you use ConfirmDialog
often and in multiple places of your code consider this:
var MessageBox = {};
MessageBox.confirm = function(kwArgs) {
var confirmDialog = new ConfirmDialog(kwArgs);
confirmDialog.startup();
var deferred = new Deferred();
var signal, signals = [];
var destroyDialog = function() {
array.forEach(signals, function(signal) {
signal.remove();
});
delete signals;
confirmDialog.destroyRecursive();
}
signal = aspect.after(confirmDialog, "onExecute", function() {
destroyDialog();
deferred.resolve('MessageBox.OK');
});
signals.push(signal);
signal = aspect.after(confirmDialog, "onCancel", function() {
destroyDialog();
deferred.reject('MessageBox.Cancel');
});
signals.push(signal);
confirmDialog.show();
return deferred;
}
Your code will be more readable and you will not have to deal with cleaning up:
MessageBox.confirm().then(function() {
console.log("MessageBox.OK")
});