Поделиться через


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.html

  • Anonymous
    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 removed

  • Anonymous
    August 06, 2014
    Just wondering: will postMessage and CloseCustomActionDialogRefresh/CloseCustomActionDialogNoRefresh work in IE8?

  • Anonymous
    August 19, 2014
    The comment has been removed

  • Anonymous
    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.