RSS
Twitter
LinkedIn

 

2013… a New Year, a New SharePoint Version and a New Set of Challenges - Part 2: App Parts, iFrames and PostMessage Resizing

 

Once an App is deployed to SharePoint site, it is listed on the 'Site Contents' page of the host web (is also listed under 'Apps in Testing' on O365 Developer Sites). Users can access (or 'Start') a chosen App by simply selecting it from the list. When opened in this way, the App runs in full-screen mode (via the App Web).

Alternatively, an App can be added to any SharePoint Wiki page or Web Part page in the form of an 'App Part' (a new type of Web Part that is represented by the ClientWebPart class). Like any other Web Part, it appears in the SharePoint 2013 UI from which users add Web Parts.

(In my previous post I covered how to easily create some very simple 'Apps' and 'App Parts' in SharePoint 2013, using Napa Office 365 Development Tools, and some fundamental differences required for each to work correctly)

 

'App Parts' are essentially wrappers for an iframe element that surface a particular page of the App. (in our case 'ClientWebPart.aspx')

The use of 'iframes' is a significant difference compared to the average SharePoint 'Web Part', as any html output from a normal 'Web Part' is rendered 'directly within' the html of a SharePoint Wiki page or 'Web Part Zone' of a Web Part page.

Now I'm not saying it isn't possible to code an iframe into an average 'Web Part', but to my knowledge this wasn't generally/previously regarded as a 'best practice approach' ...and developers (as well as content managers, power users etc) may have to consider the possibility of network overheads arising from 'page loads' if/when large numbers of 'App Parts' are added to a single Wiki or Web Part page, due to each of the 'iframe elements' resulting in an additional 'http get request' (especially when dealing with the Cloud and o365).

 (I'm sure some would argue that a retrieving the entire html of the 'Page' and 'Web Parts' in a 'single http get request' isn't preferable compared to the 'multiple get requests' involved with 'App Parts' and their iframes ...but until I can locate or produce some performance info to prove this either way, I'll leave that discussion for another day ...so I digress).

 

So what does all mean for developers moving to SharePoint 2013?

According to Eric Shupps 'Introducing the SharePoint 2013 Application Model'

For starters, it means a lot more thought will need to be put into how an application is constructed and deployed. The app model is best suited to HTML + Javascript solutions - traditional code-behind ASP.NET and SharePoint developers will have to enhance their skill set in order to adapt.

Well, one of the first examples of this 'required adaption' that I came across when dealing with 'App Part' development, was dealing with 'dynamically loaded html content'.

To demonstrate what I mean I'll begin with another simple 'App Part', which I'll call 'DynamicDivSharePoint2013App'.

Created using 'Napa Office 365 Development Tools', I get the standard x5 file starting point and make the necessary changes required to the 'ClientWebPart.aspx' and 'App.js' files (see previous post)

... add a new 'Div' element

 

 

..and a couple of JavaScript hyperlinks (which will be used to resize the 'DynamicDiv' element).

 


 

...and finally create the associated 'resize div' function (in this case 'ResizeDynamicDiv') in the App.js file.

 

When the App is then published

 

...and the 'App Part' added to a SharePoint Wiki page

 

We get the html output as expected

 


...however, when the 'Large Div' link is then selected, the larger output results in 'horizontal' and 'vertical' scroll bars within the 'App Part', which appear due to the size of the iframe used by the 'App Part' remaining 'static' whilst the height and width of dynamic html output (from the underlying 'ClientWebPart.aspx') increases

 

Now compared to 'normal Web Parts' this is a new problem that developers might not have previously come across, but may now have to deal with when working with 'App Parts', as 'normal Web Parts' don't (usually) use iframes to display their content.

(oh and if you're thinking of just setting the 'height' and/or 'width' in the 'Web Part Properties'... think again, as they relate to the parent 'wrapper' of the Web Part and not the iframe element within it)


 

It is possible to set the initial 'Width and Height' properties via the 'App Properties' of the App itself...

(example via Napa) .. but again, these aren't dynamic, so still won't actually resolve the issue for dynamic content.

 

Luckily I came across the following post from Richard diZerega (... I really was surprised on how little SharePoint 2013 related information I could actually find on this subject), Optimizing User Experience of Apps for SharePoint 2013, which clearly states:

Resizing is controlled by the app part's height and width web part properties, which are ultimately applied to the height and width of the iframe that gets rendered. These properties can be configured to a default size by the developer in the Elements.xml, but can be changed by a site designer when placed on a page. Unfortunately, app parts do not auto-size as the content contained in them grows. Additionally, an app page cannot walk the DOM hierarchy outside the page to adjust itself (this is blocked across domains).

To achieve this Microsoft has implemented the HTML5/javascript postMessage framework to achieve resizing from an 'App Part' on Wiki/Web Part page.
window.postMessage enables safe cross-domain communication between a parent page and iframe page, provided they are listening for messages.

So my second challenge for 2013... dynamic resizing of a SharePoint 2013 App Part using the postMessage framework.

 

To achieve this I created the following 'PostResizeMessage' JS function to the 'App.js' file...

 

function PostResizeMessage() {
 var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);
 var regex = new RegExp(/[Ss]ender[Ii]d=([\daAbBcCdDeEfF]+)/);
 results = regex.exec(this.location.search);
 if (null !== results && null !== results[1]) {
  target.postMessage('<message senderId=' + results[1] + '>resize(' + ($(document).width() )      + ',' + ($(document).height()) +')</message>', '*');
 }
}

 

...and added the call to the end of the relative function (in this case 'ResizeDynamicDiv')

 

You can also add a call within the '$(document).ready(function ()' or 'sharePointReady()' function, to resize the iframe of the 'App Part' on the initial page load.

(... like I said, I was really was surprised on how little information I could actually find on this subject relating to SharePoint 2013, so apologies if it's not 100% 'best practice')

 

One final step that I also make, mainly for testing/demo purposes, is to add a border to 'DynamicDiv' element via the App.css file (this makes the resizing of the DynamicDiv more visible)

 

Now when the 'App Part' is re-published ...

 

..and the 'Large Div' link is selected, the larger output no longer results in any 'horizontal' or 'vertical' scroll bars within the 'App Part'

 

 

Happy coding...

 

Published by aobi

Comments

 

Velin Georgiev said:

Good one! Thanks a lot!

April 2, 2013 8:40 AM
 

Nico said:

Thanks dude, worked like a charm :)

September 13, 2013 3:31 PM
 

Manoj Mittal said:

Good Article, I tried that one with Sharpoint Hosted Apps using both Napa Tool and Visual Studio, Its working superb !!

But its not working with Provider Hosted App, I am developing AppPart @ local machine with self signed certificate.

Some more Details:-

I created two Provider Hosted appPart like Provider and Consumer.

Both having different Client Id and Client Secret and having same Certificate with same issuer id.

Could you please help on that !!

Thanks

April 10, 2014 11:24 AM
 

aobi said:

Glad to hear you found the post useful Manoj.

If you're looking into how to get 'provider' and 'consumer' communications between app parts working, then I would suggest taking a look at the following post:

mysharepointinsight.blogspot.co.uk/.../how-to-pass-parameters-between-your-app.html

April 10, 2014 11:53 AM
 

Manoj Mittal said:

Many Thanks !!

Now its working with both SharePoint Host appPart as well as Provider Hosted appPart.

April 10, 2014 12:02 PM