Learn more about DEG’s Portals & Collaboration
practice and Microsoft
partnership.

Regardless of the hosting type of your SharePoint app (SharePoint Hosted or Provider Hosted), when using App Parts, the SharePoint’s host website will display your app content or page inside an iframe.

nick_a_sharepoint_resize_angularjs

The Problem: Iframes Do Not Resize Height Or Width Automatically

  • Iframes need a static width and height to be set.
  • The static width and height for your iframe is first set in your App Part elements.xml file.
  • This is problematic because it often causes unnecessary horizontal and vertical scroll bars around your app part.
 <ClientWebPart Name="Slack for SharePoint" Title="Slack for SharePoint"  DefaultWidth="300" DefaultHeight="200">

Now, if your SharePoint App Part displays any content dynamically (Async calls, DOM manipulation, etc.), its window size will change, but unfortunately its container iframe will not.

I ran into this issue when doing app development for a SharePoint online Office 365 app (Slack for SharePoint).

There are multiple articles online explaining in detail the issue and resolution to this problem. However, I could not find a reusable AngularJS solution that would work without listening to events.

The Solution: Automatically Resize Iframe When DOM Content Changes

It all comes down to leveraging HTML5’s post message to communicate with the parent window hosting the App P art iframe.

window.parent.postMessage('<message senderId=12345ABCD>resize(100%,800px)</message>', '*');

From the example above, senderId is the App Part ID sent to your app page as a query string parameter – 100 percent is the desired width and 800px is the desired height.

Now, to automatically resize your SharePoint App Part when your window size changes, you will need to listen to the window resize event, calculate your new height, and send the message to the parent window.

Not too shabby right? Except window resize only triggers when your browser window is manually resized, not when content is loaded.

If you are using AngularJS, I created a directive that will check your app container’s height on every $digest cycle. In other words, every time your content changes, it will automatically resize the parent iframe.

<ng-app-frame minheight="80">
.directive('ngAppFrame', ['$timeout', '$window', function ($timeout, $window) {
    return {
        restrict: 'E',
        link: function (scope, element, attrs) {

            element.css("display", "block");
            scope.$watch
            (
                function () {
                    return element[0].offsetHeight;
                },
                function (newHeight, oldHeight) {

                    if (newHeight != oldHeight) {
                        $timeout(function () {
                            var height = attrs.minheight ? newHeight + parseInt(attrs.minheight) : newHeight;
                            var id = getQsParam("SenderId")
                            var message = "<message senderId=" + id + ">resize(100%," + height + ")</message>";
                            $window.parent.postMessage(message, "*");
                        }, 0);// timeout needed to wait for DOM to update
                    }
                }
            );
        }
    };

How did this solution work for you? Please let us know in the comments section if you have any of your own feedback.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Comments