Dialogs in OfficeJS

I have been working on a number of projects for my customers and recently, dialogs have taken front and center stage. The Office.context.ui Dialogs are powerful, albeit a tad confusing and the documentation suffers from a few easily missed points.  Here is the documentation:

But in this post, I hope to explain everything I have learned. To start off with here is the code to issue the dialog:

[code lang=”javascript” collapse=”true” title=”click to expand if the embedding below is not visible.”]
Office.context.ui.displayDialogAsync(‘https://localhost:3000/function-file/dialog.html’,
{ height: 20, width: 30, displayInIframe: true },
function (asyncResult) {
dialog = asyncResult.value;
// callbacks from the parent
dialog.addEventHandler(Office.EventType.DialogEventReceived, processMessage);
dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
});
[/code]

Office.context.ui.displayDialogAsync('https://localhost:3000/function-file/dialog.html',
{ height: 20, width: 30, displayInIframe: true },
function (asyncResult) {
dialog = asyncResult.value;
// callbacks from the parent
dialog.addEventHandler(Office.EventType.DialogEventReceived, processMessage);
dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
});
view raw dialog.js hosted with ❤ by GitHub

What this dialog does is opens as a modal form in a frame over the application (in Office Web Apps). It looks like this:

screen.PNG

As you can see the dialog is modal. But what is really important are the two event handlers you need to register to be able to get back to your code:

[code lang=”javascript”]
dialog.addEventHandler(Office.EventType.DialogEventReceived, processMessage);
dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
[/code]

The first one is an event receiver and really this is the event handler for errors, such as being unable to open the dialog or, most importantly, the user closed the dialog by clicking the (X) in the upper right of the dialog. There are a series errors you can catch, but specifically, the dialog cancel is this:
12006 The dialog box was closed, usually because the user chooses the X button.
The second one is a handler for messages coming from the dialog. These messages can be anything, but is usually a string or a JSON string. You can send a message from the dialog like this:

[code lang=”javascript”]
Office.context.ui.messageParent(‘{message}’);
[/code]

When the dialog issues a message using the code above, the function defined in the event handler is called. For example, if the user clicks an OK button or Submit button, you can pass the stringified values from the form back to the callback function. From there the dialog actually remains open until the caller issues a close, like this:

[code lang=”javascript”]
// close the dialog
dialog.close();
[/code]

In the example above where I make the displayDialogAsync call, you will see I defined the SAME callback function for both dialog events. I did this because the results can be parsed by the same function. Here is what my function look like:

[code lang=”javascript” collapse=”true” title=”click to expand if the embedding below is not visible.”]
function processMessage(arg) {
// close the dialog
dialog.close();
// procress the result
if(arg.error == 12006) {
// user clicked the (X) on the dialog
sendEvent.completed({ allowEvent: false });
} else {
if(arg.message=="Yes") {
// user clicked yes
sendEvent.completed({ allowEvent: true });
} else {
// user clicked no
sendEvent.completed({ allowEvent: false });
}
}
}
[/code]

function processMessage(arg) {
// close the dialog
dialog.close();
// procress the result
if(arg.error == 12006) {
// user clicked the (X) on the dialog
sendEvent.completed({ allowEvent: false });
} else {
if(arg.message=="Yes") {
// user clicked yes
sendEvent.completed({ allowEvent: true });
} else {
// user clicked no
sendEvent.completed({ allowEvent: false });
}
}
}
My previous blog post references all the code for the dialog:

13 thoughts on “Dialogs in OfficeJS”

  1. Hi David, do you know if it’s possible to use Office.context.mailbox in the dialog window? I want to call either Outlook rest api or EWS, but both of them require Office.context.mailbox for authentication, (e.g. Office.context.mailbox.getCallbackTokenAsync()).
    If that’s not possible/recommended, how would you advise to pass email data to the dialog?
    Thanks!

    1. You should be able to use Office.context.mailbox as long as you did an Office.initialize. Is there a specific error or problem you are getting?

      However, I have found that it is unnecessary to perform mailbox level work in a dialog. If you collect the information you need before you enter the dialog, you can store it in JSON format in an browser session storage item or if you need to perform an action after a user interaction, you can use MessageParent to send a message back to your code in the function-file or taskpane in order to perform the work and return the data to the dialog, again with session storage. If you do not perform a dialog.close() on the reciept of the message, the dialog will remain open. My OfficeJS.dialogs library has some examples of how to perform two-way communication between your taskpane/function-file and the dialog.

  2. Thanks David. I’m using browser’s local storage for now, I guess that’s you were referring to as well. When I was trying to get hold of Office.context.mailbox in the dialog, mailbox was “undefined”. It must be one of the limitation of dialog api.

  3. Hi DAVID
    I have been working on an excel add-in and using dialog API to show one of my HTML page and what i want is I have a button on that HTML page which is opened in dialog when the user clicks on that button I need to create a table in excel .could you please guide me on this.

    1. If you are using the OfficeJS.dialogs, then it depends on whether you want the form to close on your button click, but what you will do is set the code to create the table in the syncResult, defined in the Form call:
      https://github.com/davecra/OfficeJS.dialogs#Form
      – Show([url],[height],[width],[handleclose],[asyncresult])
      In the button call, you simply issue a messageParent call. Like this in the example:
      Office.initialize = function(reason) {
      $(document).ready(function () {
      $(“#okButton”).click(function() {
      // notify the parent – FunctionFile
      Office.context.ui.messageParent(JSON.stringify(
      {
      “FibbyGibber”: “rkejfnlwrjknflkerjnf”,
      “DoDaDay”: “Hahahaha”,
      “Message” : “My custom message.”
      }));
      });
      });
      };

      This will call the asyncResult() function you defined in Show(). Once you are in that function you used the Excel object model to create the table. If you want the form to remain open when the user clicks the button set the HandleClose parameter to FALSE. You will then have to initiate the Form.CloseDialogAsync() yourself to close the dialog when you want it to go away.

      Let me know if this helps.

  4. Hi David,

    Thanks for information on dialog api, I was working on combination of word addin and angular 6, I have issue with dialog window its not triggering the component of passing url its just rending the html page what I passed in the string, how can I show my login page in dialog window from angular 6 addin, please suggest me

    1. Hi Rahul, I am not certain I understand. If you instance a dialog with a local url that redirects to a remote url should work. But if you load an external url into a dialog that tries to redirect to another url, that will fail because of CORS, I believe. Do you have a sample of the code?

      1. Hi David,

        Thanks for reply, here you can see this
        https://docs.microsoft.com/en-us/office/dev/add-ins/develop/dialog-api-in-office-add-ins#use-the-office-dialog-api-with-single-page-applications-and-client-side-routing

        so, the dialog window is opening independently, so when I pass my application url(ex: httpsl:ocalhost:4240/src/app/login/login.html) its just showing the html mock-up.
        I can share only this code right now

        openDlg() {
        try {
        console.log(window.location.origin);
        let openWindow = window.location.origin + “/src/app/login/login.html”;
        console.log(openWindow);
        let dialog = new DialogLauncher(openWindow, 550, 300,);
        console.log(“::Open popup::”);
        DialogLauncher.dataReceivedEvent.subscribe((data) => {
        console.log(“Received Data from error dialog window : ” + data);
        })
        window.setTimeout(dialog.launchDialog.bind(dialog), 50);
        }
        catch (e) {
        console.error(e)
        }

      2. David

        I was added my comments and expecting your relply, to understand better, can you tell me how router will work in dialog ? we can’t see any html(exluding index.html) in SPA output folder(app or dist/app) of angular 6, please suggest the right approach to open a dialog component with component event trigger in ang6.

      3. Does the login.html page have an Office.initialize() call? When the initial page is loaded that page must initialize with Office. Like this:

        /**
        * Starting point when Office/Outlook initializes this page
        * @param {string} reason
        */
        Office.initialize = function(reason) {
        /**
        * Starting point for the page load
        */
        $(document).ready(function () { }
        }

        Then you need to follow a flow like this to perform a login: https://docs.microsoft.com/en-us/office/dev/add-ins/develop/dialog-api-in-office-add-ins#use-the-dialog-apis-in-an-authentication-flow

        But you can also use the office-js-helpers for login as well: https://github.com/OfficeDev/office-js-helpers

        Their login sample takes a lot of the guesswork out of getting login pages to work.

  5. Hi, Thanks a lot for developing this wonderful library. I installed this using npm install. But how to use it inside the addin? I cannot see any of your methods. Do i have to update webpackconfig.json?

Leave a Reply to AbhishekCancel reply