Resizing your add-in showing in a modal dialog
SharePoint has an option to resize the app-part or add-in iframe from within the add-in. See for example 4 Steps to smarter App Part resizing.
This only works for a ClientWebPart (app-part), and does not work when you are using a HostWebDialog. So if you specify a ribbon custom action, or an edit control block custom action in your add-in, using HostWebDialog then the postMessage option will not work.
Custom Action:
<CustomAction Id="0ad636fa-afee-46a6-99c0-cc548e93a165.RibbonCustomActionSample"
RegistrationType="List"
RegistrationId="101"
Location="CommandUI.Ribbon"
Sequence="10001"
Title="Sample resize popup"
HostWebDialog="true"
HostWebDialogHeight="180"
HostWebDialogWidth="280">
JavaScript:
var message = "<Message senderId=" + senderId + ">"
+ "resize(" + width + "," + height + ")</Message>";
window.parent.postMessage(message, "*");
So that is a bummer. I also looked at the autoResize option available for the SharePoint dialog, see SharePoint 2010: Easy Dynamic Resize of Dialogs. As stated there, the code (SP.UI.ModalDialog.get_childDialog) is called from within the
popup content, and this code is only available from within the SharePoint site itself, and is not an option when using an add-in.
Now I went and put these things together to enable the resizing of the add-in dialog from withing the add-in. For this you need to handle the (on)message event from within the SharePoint site. And
for convenience I have enabled the usage of the same message format as used for a ClientWebPart, so you can use the same add-in code for resizing the ClientWebPart and the HostWebDialog.
For development and test purposes I have created a SharePoint hosted add-in with the above mentioned user custom action, that is available from within the document library.
Then I created a Sandboxed Solution that will add a ScriptLink to the site with a reference to the resize script. You can download the add-in and sandbox solution as ResizePopupSample.zip.
Install the app in your dev site, or dev app catalog and then install it in a dev site. And install the sandbox solution to enable resizing from within your add-ins. You could also add a scriptlink on the AppInstalled event
of a provider hosted app, but this will not fire when using app stapling. You cannot add a scriptlink from
within a SharePoint hosted app (or so I thought, see Update 5/13/2016).
If you then go to a document library, and select a document, you can see the Sample option of the add-in in the documents tab in the Manage section. If you click this,
the dialog will show and you will have two options to test resizing. One by setting the size yourself, and one automated test that enlarges the dialog end then shrinks the dialog back again.
So the main part is lots of boring sizing javascript code in the ResizeDialog function. And some code to handle the message event:
window.receiveDialogResizeMessage = window.receiveDialogResizeMessage || function (event) {
if (event.data != null && event.data.toLowerCase().indexOf('<message ') == 0) {
try {
var parser = new DOMParser();
var message = parser.parseFromString(event.data, "text/html").getElementsByTagName("message")[0];
if (message.attributes["senderid"].value != '') // check sender
return; // popups don't have a senderId so this is from a add-in part.
var size = message.textContent.replace("resize(", "").replace(")", "").split(',');
if (size != null && size.length == 2) {
window.ResizeDialog(size[0], size[1]);
}
}
catch (e) {
if (window.console)
console.log('Error parsing received message: ' + e);
}
}
};
window.attachedResizeDialog = window.attachedResizeDialog || false;
if (!window.attachedResizeDialog) {
if (window.addEventListener) {
addEventListener('message', receiveDialogResizeMessage, false);
window.attachedResizeDialog = true;
} else {
attachEvent('onmessage', receiveDialogResizeMessage);
window.attachedResizeDialog = true;
}
}
I have used the DOMParser and some replace statements here, but you probably could use a regular expression instead. For the full script see: ResizeDialog.js
I have tested this with minimal download strategy on and off, and with recent versions of Firefox, Internet Explorer and Chrome. Still as I always state,
test this yourself before using this.
Update 4/17/2016
Have updated the ResizePopupSample.zip, as I found out the sandbox solution 'EnableResizeDialog.wsp' did not function properly. I now fixed this issue, and also set the project property 'Include Assembly In Package' to False, as this is a no code sandbox solution, and no assembly is needed.
If you downloaded this file earlier, you can now download the updated file.
Update 5/13/2016
Well as I wasn't a 100% sure I was correct when mentioning that you can't add a ScriptLink from a SharePoint hosted add-in, so I went and tested this and
I found out that it was possible after all. I have now added a sample that describes how this can be done Add a ScriptLink on the host web from a SharePoint hosted app with JSOM
Update 6/1/2016
I thought it worked with minimal download strategy (MDS) on, but I noticed it didn't. So I have updated the sandboxed solution in the .zip file and
the ResizeDialog.js file. If you already downloaded and installed the sandbox solution, please
update the javascript file in the Style Library, and make sure that the file gets refreshed to avoid caching issues.
I should have known, that this would be an issue, as anonymous javascript functions don't work well with MDS. Code added:
function InitResizeDialogAfterMinimalDownload() {
if (window.asyncDeltaManager && window.asyncDeltaManager.add_endRequest) {
asyncDeltaManager.add_endRequest(function () {
InitResizeDialog();
});
}
}
if(window._spBodyOnLoadFunctions) {
_spBodyOnLoadFunctions.push(InitResizeDialogAfterMinimalDownload);
_spBodyOnLoadFunctions.push(InitResizeDialog);
}
That fixed the issue with MDS.
Update 6/3/2016
I have noticed an issue with office web apps and javascripts added with a scriptlink. When debugging script for a Word Add-In I noticed
error messages ReferenceError: _spBodyOnLoadFunctions is not defined. I also found that
also my own scripts gave out these errors. Now I have updated everything (also script above) with a check if _spBodyOnLoadFunctions is available, before adding
functions to this array. If you already installed the solution, please update the javascript file in the Style Library.