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