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
Comments
Anonymous
March 10, 2013
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!Anonymous
March 16, 2013
This is absolutely great post, thanks browse for cloud www.sqlservermanagementstudio.net/.../microsoft-sql-azure.htmlAnonymous
October 17, 2013
I am getting error The 'HostWebDialog' attribute is not declared. App deployment is failed with error "Is an Unexpected Token. Please help me..Anonymous
February 25, 2014
Thanks. this was what I needed in order to close my dialog in Provider-Hosted App.Anonymous
April 26, 2014
The comment has been removedAnonymous
August 06, 2014
Just wondering: will postMessage and CloseCustomActionDialogRefresh/CloseCustomActionDialogNoRefresh work in IE8?Anonymous
August 19, 2014
The comment has been removedAnonymous
December 10, 2014
Is there a way to post context from the dialog to the host web list?Anonymous
January 28, 2016
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.