Created a DialogBuilder object, but having issues with subscribing/unsubscribing to dialog events var WorkflowDialogBuilder = _.once(function () {
    'use strict';
    var workflowDialog = $('#WorkflowDialog');
    var workflowDialogContent = $('#WorkflowDialogContent');

     var events = {
        onApplyChangesSuccess: 'onApplyChangesSuccess',
        onValidationFailed: 'onValidationFailed',
        onDialogOpen: 'onDialogOpen'
    };

    var dialogConfig = {
        autoOpen: false,
        buttons: {
            OK: function () {
                var form = $(this).find('form');

                if (form.valid()) {
                    var self = this;
                    $.ajax({
                        type: "POST",
                        url: 'Form/Save',
                        dataType: 'json',
                        data: form.serialize(),
                        success: function (data) {
                            $(self).dialog('close');
                            $(self).trigger(events.onApplyChangesSuccess, data);
                        },
                        error: function (error) {
                            console.error(error);
                        }
                    });
                } else {
                    $(this).trigger(events.onValidationFailed);
                }
            },
            Cancel: function () {
                $(this).dialog('close');
            }
        },
        open: function () {
            $(this).trigger(events.onDialogOpen);
        }
    };

    workflowDialog.dialog(dialogConfig);

    return {
        onApplyChangesSuccess: function (event) {
            workflowDialog.on(events.onApplyChangesSuccess, event);
        },
        onDialogOpen: function (event) {
            workflowDialog.on(events.onDialogOpen, event);
        },
        onValidationFailed: function (event) {
            workflowDialog.on(events.onValidationFailed, event);
        },
        buildAddTaskDialog: function () {
            workflowDialogContent.load('NewTaskDetails', function () {
                //Load ViewModel client-side helpers and then when its ready, open the dialog.
                $.getScript('../Scripts/Orders/NewTaskDetailsModel.js', function () {
                    workflowDialog.dialog('open');
                });
            });
        },
        buildAddOrderDialog: function () {
            workflowDialogContent.load('NewOrderDetails', function () {
                //Load ViewModel client-side helpers and then when its ready, open the dialog.
                $.getScript('../Scripts/Orders/NewOrderDetailsModel.js', function () {
                    workflowDialog.dialog('open');
                });
            });
        }
    }
}


So, I've made the above builder. It is responsible for initializing a dialog element, opening it, and responding appropriately when the dialog closes.

Now, I was pretty happy with this implementation until I realized that, given the following scenario, events were subscribing and not unsubscribing.

//User calls WorkflowDialogBuilder.buildAddTaskDialog();
//NewTaskDetailsModel.js is loaded.
//NewTaskDetailsModel.js calls the following:

WorkflowDialogBuilder.onValidationFailed(function () {
    console.log("NewTaskDetailsMode.js onValidationFailed fired.");
});

//AddTaskDialog is closed by the user. NewTaskDetailsModel.js has already been loaded.
//AddTaskDialog continues to be subscribed to DialogBuilder's onValidationFailed.

//User calls WorkflowDialogBuilder.buildAddOrderDialog();
//User works with the dialog and clicks 'OK' to apply validation.
//AddTaskDialog's onValidationFailed event runs because WorkflowDialogBuilder triggers an event.


Now, I can think of one very simple solution to this. I could simply respond to the dialog's onClose event and, at that pont in time, unsubscribe all events.

Question: Does that seem like a proper solution? Or, have I gone down a bad path from the getgo and should rethink my architecture? If so, advice on how to restructure?
I would refactor it into a plugin that takes the content as an option. Then you will have two instances of "dialog controllers" each with its own events.

Have a look at the "plugin with data" example in the jQuery docs.

http://docs.jquery.com/Plugins/Authoring#Data

You'd set it up like

&lt;div id="addTaskDialog"&gt;&lt;/div&gt;
&lt;div id="addOrderDialog"&gt;&lt;/div&gt;
&lt;script type="text/javascript"&gt;
//...
$("#addTaskDialog").workflowDialog({model:"NewTaskDetailsModel.js"});
$("#addOrderDialog").workflowDialog({model:"NewOrderDetailsModel.js"});
// attach events to either
&lt;/script&gt;


Otherwise I'd switch to $.unbind followed by $.bind in the subscribe functions.