Leveraging SharePoint dialogs in Apps for SharePoint


One of the creative ways Apps for SharePoint can be exposed in a site is through the SharePoint dialog.  In this way, apps can deliver contextual capabilities to a SharePoint site.  Dialogs will typically be launched from custom actions in the app.  In this post I will discuss how to launch an app through the SharePoint dialog, pass information into the app, and close the dialog from within the app.

Launching the Dialog

Launching an app page in the SharePoint dialog requires the use of a custom action.  Apps for SharePoint support Menu Item Custom Actions and Ribbon Custom Actions.  Both of these can be deployed to the Host Web or the App Web.  The wizard for adding these custom actions makes it very easy to scope custom actions appropriately as is shown in the table below:

  Ribbon Custom Action Menu Item Custom Action
List Template X X
List Instance X X
Content Type   X
File Extension   X

 

As you can see in the table above, Menu Item Custom Actions have additional flexibility to scope against specific Content Types or File Extensions.  Ribbon Custom Actions are unique because they scope to a specific ribbon tab and group, which a wizard will prompt you for when added to an app:

In additional to location, Ribbon Custom Actions typically have icons associated with them.  Ribbon icons are especially challenging when deploying the custom action to the host web.  An App for SharePoint can only deploy images to the app web (via module) or remote web, neither of which will render nicely in the ribbon of the host web.  The solution is to specify the image source as a Base64 encoded image as seen below:

 <CommandUIDefinitions>
    <CommandUIDefinition Location=Ribbon.Documents.New.Controls._children>
        <Button Id=Ribbon.Documents.New.UploadToAzureMediaSvcButton
            Alt=Upload to Media Services
            Sequence=1
            Command=Invoke_UploadToAzureMediaSvcButtonRequest
            LabelText=Upload to Media Services
            TemplateAlias=o1
            Image32by32=data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/…
            Image16by16=data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/…

 

I created a quick tool to Base64 encode images, which is provided at the end of this post.  Here is the UI of that tool:

A custom action can be converted to leverage the SharePoint dialog by adding the HostWebDialog, HostWebDialogHeight, and HostWebDialogWidth attributes to the CustomAction element in the Elements.xml:

<?xml version=1.0encoding=utf-8?>
<Elements xmlns=http://schemas.microsoft.com/sharepoint/>
    <CustomAction Id=a76f4430-c8b1-4317-b673-260429ca6dc1.UploadToAzureMediaSvc
        RegistrationType=List
        RegistrationId=851
        Location=CommandUI.Ribbon
        Sequence=10001
        Title=Upload to Azure Media Services
        HostWebDialog=true
        HostWebDialogHeight=420
        HostWebDialogWidth=510>

 

Passing Context to the Dialog

App will generally get contextual information from URL parameters or information posted from SharePoint.  Custom actions have a number of dynamic URL parameters they can leverage for contextual information:

URL Parameter Action Type Description
HostUrl Both URL of the host web
SiteUrl Both URL of the host site collection
Source Both The absolute path of the page invoking the custom action
ListUrlDir Both Relative URL path for the contextual list
ListId Menu Item The ID of the contextual list
SelectedListId Ribbon The ID of the contextual list
ItemId Menu Item The ID of the contextual item
SelectedItemId Ribbon Comma-separated list IDs for selected items

 

Closing the Dialog

Autohosted and Provider-hosted Apps for SharePoint are hosted outside of SharePoint, and as such can’t leverage typical SharePoint scripts to close the dialog (ex: SP.UI.ModalDialog.commonModalDialogClose()).  Luckily, I have hunted through many lines of core.js to find you the solution!  Similar to resizing app parts (client web parts), we can use the HTML5 postMessage API to close the dialog from the app (and optionally refresh the parent page).  This shouldn’t come as a surprise, since the postMessage API was meant to provide cross-domain communication and is used in other app scenarios.  CloseCustomActionDialogRefresh and CloseCustomActionDialogNoRefresh are the two messages SharePoint is “listening” for to close the dialog.  I wrapped these in a simple function I can releverage across all my apps:

 function closeParentDialog(refresh) {
    var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);
    if (refresh)
        target.postMessage(‘CloseCustomActionDialogRefresh’, ‘*’);
    else
        target.postMessage(‘CloseCustomActionDialogNoRefresh’, ‘*’);
}

 

Final Thoughts

Leveraging custom actions with the SharePoint dialog makes an app feel even more integrated than with app parts.  They provide contextual integration and are the only mechanism for pushing a change in UI on the host web (remember an app part is optionally added by a user).  Below are links to a code sample and the Image Encoder tool mentioned above:

App for SharePoint with dialogs:  ImageEncoder.zip

Comments (9)

  1. Dave Smith says:

    Great find with the postMessage and CloseCustomActionDialogRefresh/CloseCustomActionDialogNoRefresh.  I often used the SharePoint dialog in 2010, so it is nice to know we can use it in similar ways for apps.  Thanks!

  2. Sarah says:

    This is absolutely great post, thanks

    browse for cloud

    http://www.sqlservermanagementstudio.net/…/microsoft-sql-azure.html

  3. Nagesh says:

    I am getting error The 'HostWebDialog' attribute is not declared. App deployment is failed with error "Is an Unexpected Token.

    Please help me..

  4. Nikolay says:

    Thanks. this was what I needed in order to close my dialog in Provider-Hosted App.

  5. Vince says:

    Thanks Richard…very useful & that tool is fab 🙂

  6. Ernst Wolthaus says:

    Just wondering: will postMessage and CloseCustomActionDialogRefresh/CloseCustomActionDialogNoRefresh work in IE8?

  7. Elena says:

    Hi Richard,

    Is there way to update HostWebDialog, HostWebDialogHeight, and HostWebDialogWidth properties using CSOM?

  8. Vamsi says:

    Is there a way to post context from the dialog to the host web list?

  9. Sean says:

    Is there a way to resize Modal Dialogs launched in this fashion? There doesn't appear to be a "message" handler to post to on the hostweb for resizing these as there is for app parts. None of the "classic" ways of resizing a modal dialog (when not dealing with apps) work.