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.0" encoding="utf-8"?><Elements xmlns="https://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:  SharePointDialogs.zip

Image Encoder Tool: ImageEncoder.zip