Use dialogs in tabs

Add modal dialogs (referred as task modules in TeamsJS v1.x) to your tabs to simplify the user experience for any workflows that require data input. Dialogs allow you to gather user input in a Microsoft Teams-Aware modal window, such as editing Planner cards. You can use dialogs to create a similar experience.

The two main operations of dialogs involve opening and closing (submitting) them. The functions are slightly different for earlier versions (prior to v2.x.x) of the TeamsJS library:

// Open HTML dialog
microsoftTeams.dialog.url.open(
    urlDialogInfo: UrlDialogInfo, 
       submitHandler?: DialogSubmitHandler, 
       messageFromChildHandler?: PostMessageChannel
): void;

// Open Adaptive Card dialog
microsoftTeams.dialog.adaptiveCard.open(
    adaptiveCardDialogInfo: AdaptiveCardDialogInfo,
    submitHandler?: DialogSubmitHandler
): void;

// Submit HTML dialog (AC dialogs send result from Action.Submit)
   microsoftTeams.dialog.url.submit(
    result?: string | any,
    appIds?: string | string[]
): void;

Note

The dialog.submit property can only be called within a dialog.

The following sections explain the process of invoking a dialog from a tab and submitting the result.

Invoke a dialog from a tab

Note

Starting with TeamsJS v2.8.x, the dialog namespace supports Adaptive Card-based dialogs. The tasks namespace is still supported for backward-compatibility, however best practice is to update tasks.startTask() call to dialog.url.open or dialog.adaptiveCard.open for HTML and Adaptive Card-based dialogs, respectively. For more information, see the dialog namespace.

You can invoke either an HTML or Adaptive Card dialog from a tab.

HTML dialog

 microsoftTeams.dialog.url.open(urlDialogInfo, submitHandler);

The value of UrlDialogInfo.url is set to the location of the content of your dialog. The dialog window opens and UrlDialogInfo.url is loaded as an <iframe> inside it. JavaScript in the dialog page calls microsoftTeams.app.initialize(). If there's a submitHandler function on the page and there's an error when invoking microsoftTeams.dialog.url.open(), then submitHandler is invoked with err set to the error string indicating the same.

Warning

Microsoft's cloud services, including web versions of Teams, Outlook, and Microsoft 365 domains, are migrating to the *.cloud.microsoft domain. Perform the following steps before September 2024 to ensure your app continues to render on supported Microsoft 365 web client hosts:

  1. Update TeamsJS library to v.2.19.0 or later. For more information about the latest release of TeamsJS, see Microsoft Teams JavaScript client library.

  2. If you've defined Content Security Policy (CSP) headers for your app, update the frame-ancestors directive to include the *.cloud.microsoft domain. To ensure backward compatibility during the migration, retain the existing frame-ancestors values in your CSP headers. This approach ensures that your app continues to work across both existing and future Microsoft 365 host applications and minimizes the need for subsequent changes.

Update the following domain in the frame-ancestors directive of your app's CSP headers:

https://*.cloud.microsoft

Adaptive Card dialog

 microsoftTeams.dialog.adaptiveCard.open(adaptiveCardDialogInfo, submitHandler);

The value of adaptiveCardDialogInfo.card is the JSON for an Adaptive Card. You can specify a submitHandler to be called with an err string, if there was an error when invoking open() or if the user closes the dialog using the X (Exit) button.

The next section gives an example of invoking a dialog.

Example of invoking a dialog

The following image displays the dialog:

Task Module Custom Form

The following code is adapted from the dialog sample:

let urlDialogInfo = {
    title: null,
    height: null,
    width: null,
    url: null,
    fallbackUrl: null,
};

urlDialogInfo.url = "https://contoso.com/teamsapp/customform";
urlDialogInfo.title = "Custom Form";
urlDialogInfo.height = 510;
urlDialogInfo.width = 430;
submitHandler = (submitHandler) => {
        console.log(`Submit handler - err: ${submitHandler.err}`);
        alert("Result = " + JSON.stringify(submitHandler.result) + "\nError = " + JSON.stringify(submitHandler.err));
    };

 microsoftTeams.dialog.url.open(urlDialogInfo, submitHandler);

The submitHandler echoes the values of err or result to the console.

Submit the result of a dialog

If there's an error when invoking the dialog, your submitHandler function is immediately invoked with an err string indicating what error occurred. The submitHandler function is also called with an err string when the user selects X on the dialog to exit.

If there's no invocation error and the user doesn't select X to dismiss the dialog, the user selects a submit button when finished. The following sections explain what happens next for HTML and Adaptive Card dialog types.

HTML or JavaScript dialogs

After validating user input, call microsoftTeams.dialog.url.submit(). You can call submit() without any parameters if you want Teams to close the dialog, or you can pass an object or string result back to your app as the first parameter, and an appId of the app that opened the dialog as the second parameter. If you call submit() with a result parameter, you must pass an appId (or an array of appId strings of apps authorized to receive the result of the dialog). This action enables Teams to validate that the app sending the result is the same as the invoked dialog.

Teams then invokes your submitHandler where err is null and result is the object or string you passed to submit().

Adaptive Card dialogs

When you invoke the dialog with a submitHandler and the user selects an Action.Submit button, the values in the card are returned as its data object. If the user presses the Esc key or selects X to exit the dialog, your submitHandler is called with the err string. If your app contains a bot in addition to a tab, you can include the appId of the bot as the value of completionBotId in the TaskInfo (BotAdaptiveCardDialogInfo) object.

The Adaptive Card body as filled in by the user is sent to the bot using a task/submit invoke message when the user selects an Action.Submit button. The schema for the object you receive is similar to the schema you receive for task/fetch and task/submit messages. The only difference is that the schema of the JSON object is an Adaptive Card object as opposed to an object containing an Adaptive Card object as when Adaptive cards are used with bots.

The following code is the example of payload:

{
  "task": {
    "type": "continue",
    "value": {
      "title": "Title",
      "height": "height",
      "width": "width",
      "url": null,
      "card": "Adaptive Card or Adaptive Card bot card attachment",
      "fallbackUrl": null,
      "completionBotID": "bot App ID"
    }
  }
}

The following code is the example of Invoke request:

let adaptiveCardDialogInfo = {
    title: "Dialog Demo",
    height: "medium",
    width: "medium",
    card: null,
    fallbackUrl: null,
    completionBotId: null,
};

adaptiveCardDialogInfo.card = {
    "type": "AdaptiveCard",
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.5",
    "body": [
        {
            "type": "TextBlock",
            "text": "This is a sample adaptive card.",
            "wrap": true
        }
    ]
}

submitHandler = (err, result) => {
    console.log(`Submit handler - err: ${err}`);
    alert(
        "Result = " + JSON.stringify(result) + "\nError = " + JSON.stringify(err)
    );
};

microsoftTeams.dialog.adaptiveCard.open(adaptiveCardDialogInfo, submitHandler);

The next section provides an example of submitting the result of a dialog (referred as task module in TeamsJS v1.x).

Example of submitting the result of a dialog

Taking up the earlier example of invoking an HTML dialog, here's an example of the HTML form embedded in the dialog:

<form method="POST" id="customerForm" action="/register" onSubmit="return validateForm()">

There are five fields on this form but this example requires only three values, name, email, and favoriteBook.

The following code gives an example of the validateForm() function that calls submit():

function validateForm() {
    var customerInfo = {
        name: document.forms["customerForm"]["name"].value,
        email: document.forms["customerForm"]["email"].value,
        favoriteBook: document.forms["customerForm"]["favoriteBook"].value
    }
    microsoftTeams.dialog.url.submit(customerInfo, "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
    return true;
}

Dialog invocation errors

Note

The tasks namespace is replaced by the dialog namespace. The dialog namespace includes sub-namespaces for HTML (url), Adaptive Card (adaptiveCard), and bot-based (dialog.url.bot and dialog.adaptiveCard.bot) functionality.

The following table provides the possible values of err that your submitHandler receives:

Problem Error message that is value of err
Values for both TaskInfo.url and TaskInfo.card were specified. Values for both card and URL were specified. One or the other, but not both, are allowed.
TaskInfo.url and TaskInfo.card specified. You must specify a value for either card or URL.
Invalid appId. Invalid app ID.
User selected X button, closing it. User canceled or closed the dialog.

Code sample

Sample name Description .NET Node.js Manifest
Dialog sample bots-V4 This sample shows how to create dialogs using bot framework v4 and teams tabs. View View View

Next step

See also