Controlling the size of a Control Add-In

1 Feb

In the previous blog post about a PDF viewer for Business Central, I promised to come back with some tips. Here is tip #1: how to get full control over the size of a control add-in.

Final code of this example can be found on GitHub.

Control add-in example

Let’s first look at a very simple example with no size settings at all and then gradually take over control over it’s length and width.

The stylesheet is very short and used to give the control add-in some colors so we can easily recognize it on the page.

The startup script just writes some text into it.

And finally we put this thing on the Customer Card with a pageextension.

This results in a blue box with a red border on the Customer Card:

Let’s zoom in a little bit on that blue box.

First thing we notice here is that the box doesn’t display the red border at the right and the bottom. This is because by default the size of a border isn’t part of the size of the box itself. More info can be found here. So let’s first fix this by setting the box-sizing to border-box.

Which then results in a box with red borders around it.

Controlling the size

Ok, that was easy to solve. Next step is to expand the blue box to 100% of the available space and also resize when the whole page is resized.

What we need to understand is how the control add-in is added to the page. It is not just a simple HTML <div> control, but it is inside an iframe. An iframe is used to display a web page inside a web page. The iframe has its own source and acts as an independent page, embedded in the parent page.

Why is this important to know? Because the div element which represents the control add-in can’t be used to define the size. In fact the div has already width and height set to 100%. But it still doesn’t take all remaining space. And that’s because it is embedded in a parent element, the iframe, that has its own width and height set. By default, width and height of the iframe are 100px.

With Chrome DevTools we can easily inspect the elements on the page. In the picture below you see the <iframe> element and inside the iframe the <div> element of the control add-in. Notice that the <div> element has set height and width to 100%, but height and width of the <iframe> is set to 100px.

So, how can we set the height and width of that <iframe> element? First option to is specify it in the controladdin object in AL code. In fact, there are a lot of settings that can be used to set the sizes. A complete overview can be found here. I’m not going to discuss every one of them, but I would like to focus on the most asked question: how can I force the control add-in to take up as much space as possible and resize automatically?

The answer is: use the properties HorizontalStretch and VerticalStretch.

Setting the width

Let’s first look at HorizontalStretch. When you set this property to true, the control add-in will occupy width up to the maximum that has been set with the property MaximumWidth. But if you omit the maximum width property, then the control add-in will expand indefinitely. Same goes with the property HorizontalShrink. If you specify this, the control can shrink up to the minimum that has set with the property MinimumWidth. And if you omit the minimum width, then the control could even shrink to zero width. Which is not really recommended, you should set a minimum width that will keep the content of the control add-in visible.

So, let’s set the properties HorizontalStretch and HorizontalShrink, including a minimum width, and look at the result.

Now the control add-in takes up full width and it expands and resizes automatically when the page is resized.


Take a look at the properties of the iframe to see how the settings were applied.

Setting the height

So, does the same work for the height property? Yes, but limited to specific situations. The VerticalStretch property is only supported in a CardPart on Role Center pages or when it is the only content in a Card page. Same as with the width properties, the MinimumHeight and MaximumHeight can be used to limit lower and upper limits.

Before we look at setting the height of a control and letting it resize with the screen, we should think about how it should behave. Do you place other controls under the the control add-in, like I’ve done in the example above where I placed the blue box in the middle of a screen? In that case, VerticalStretch is not very useful. But in case you place the control as the last control in a page, then it would make sense to let it automatically occupy the rest of the screen.

So, let’s change the example and add the blue box on a page with only a few fields in the top. First screenshot is with no height settings applied, so the height is still the default 100px.

Let’s now set the VerticalStretch property and also set a MinimumHeight and see if that has any effect.


I’ll spare you another screenshot. With this setting, you won’t see any difference. The control add-in still has a height of 100px. The reason why this is happening is that MinimumHeight only applies when VerticalShrink is true. But VerticalShrink only applies when the add-in control is the only control on a page. The only way to control the height, is by setting the RequestedHeight property. Let’s prove that by setting RequestedHeight and look at the result.

As you can see, the blue box is now bigger. You could say, we are getting closer. Well, not really. What we want to achieve is that the blue box takes the rest of screen, and according to the documentation that is only going to happen when we place the control add-in as the only one on the page.

In the screenprint below, I have removed the two fields, and now the control add-in behaves like documented. Again, out-of-the-box this doesn’t work when you combine the control add-in with other fields on the page.

Advanced scenarios

Now that I’ve demonstrated the default behavior, it’s time to take it to the next level and figure out if we can achieve what we were looking for. Because the AL controladdin object doesn’t support this, there is only one way left: use JavaScript and directly set the desired properties on the HTML elements.

Without going to deep, the problem can’t simply be solved by setting height to 100% on the HTML iframe element. The height of the iframe will become the same as its parent, without calculating the space of the fields above. As a result, the control add-in will be larger than the screen and a scrollbar will be displayed.

The only solution I could find is to use the CSS flexbox layout. As a matter of fact, the Business Central web client is also using this property quite a lot. If you want to read more about flexbox, then I can recommend this site.

In short, what we are going to do:

  • The parent element of the iframe must become a flex container.
  • The iframe element must become a flex item
  • The iframe should not have any height settings.

Let’s start with the last bullet point and remove the height settings from the control add-in. Remember, the iframe will now get the default height of 100px. So that needs to be removed, which we will do with JavaScript.

The first two bullet points is done with JavaScript code in the startup.js. Including the code to remove the height properties from the iframe element.

We could also remove the width settings from the iframe, and modern browser like Chrome and Edge, will still show the expected result. However, Internet Explorer 11 doesn’t like that. So I leave the width settings to also support IE11.

Please note that I have added a padding of 42px to the bottom of the iframe (see line 14 in the startup.js script). That’s optional, but it just looks better to me. The value of 42px is also used by fasttabs in the web client.

And here is the result of these changes:

The code of the result can be found on GitHub.

Good luck, I hope this helps you with creating nice control add-ins for Business Central!

11 thoughts on “Controlling the size of a Control Add-In

  1. Pingback: Controlling the size of a Control Add-In | PA

  2. Hello Arend-Jan, thank you for sharing your project. It was very interesting to read 🙂 meanwhile I set up my own project. In this I would like to make a simple diagram visible on the customer card also within a control add-in. Did you already do something like that? Because it was not possible for me to make it visible in Business Central …

    • It depends where the diagram is coming from. Are you talking about the standard diagrams of Business Central? Or a 3rd party add-in?

      • Specifically, I think of Chart.js. For example, on the “Customer Card”, I want to make certain activities visible with charts. For this I use a control addin. I did exactly the same thing as Arend-Jan in his article above.

        For the diagram I use an HTML file, which I cannot integrate however, I have to bind its components in a huge string and the output I get is only:”+”

        This is my html-file:

        var html =
        ” +
        ‘Hello world’+
        ‘ ‘ +
        ‘ +
        ‘ ‘ +
        ‘ +
        ‘ ‘ +

        var control = document.getElementById(‘controlAddIn’);
        control.innerHTML = html;

        Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(‘ControlAddInReady’, null);

        • Here is again my html varable, the insert did not work at the first time…

          var html =
          ‘ +
          Hello world’+
          ‘ +
          ‘ +
          ‘ +
          ‘ +
          ‘ +

          • I’m afraid the site does not support to insert HTML in the comments.
            Can you put the code somewhere as a zip, or maybe on GitHub?

    • I’m afraid that’s not going to work. Not 100% sure, I haven’t tested it.
      Honestly, I didn’t think of the Windows Client at all, since it is at the end of its life cycle.

  3. Pingback: Extending Dynamics 365 Business Central with Add In – Listening to The Echo

  4. Hi, Thanks for this example. I have it working in my BC15 AL environment with Web Client fine. However, being new to js control add-ins. I am missing something in trying to substitute “Hello World” with Text that would be sent in a Procedure from the AL Page object with this control.

    Is there any examples of doing exactely what you are doing here, but using text set to the control by the page?

    I tried this, but the Hello World Text Never Changes to what my Page Object sends (or what I think it should be sending).

    controladdin “CSM HTML Viewer”
    {
    RequestedHeight = 300;
    MinimumHeight = 200;
    MaximumHeight = 500;
    RequestedWidth = 500;
    MinimumWidth = 250;
    MaximumWidth = 700;
    VerticalStretch = true;
    VerticalShrink = true;
    HorizontalStretch = true;
    HorizontalShrink = true;
    Scripts =
    ‘https://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js’,
    ‘src/JSScripts/CSMHTMLViewAction.js’;

    StartupScript = ‘src/JSScripts/CSMHTMLViewStart.js’;
    StyleSheets = ‘src/ControlAddins/CSMHTMLViewStylesheet.css’;

    procedure GetHTMLToShow(HTMLTextToShow: text);
    }

    On Page:

    usercontrol(CSMHtmlAddin; “CSM HTML Viewer”)
    {
    ApplicationArea = All;
    }

    trigger OnAfterGetRecord();
    begin
    SetControlAppearance();
    BLOBDescription := GetDescription();
    CurrPage.CSMHtmlAddin.GetHTMLToShow(BLOBDescription);
    CurrPage.Update();
    end;

    CSMHTMLViewStart.js

    var iframe = window.frameElement;

    iframe.parentElement.style.display = ‘flex’;
    iframe.parentElement.style.flexDirection = ‘column’;
    iframe.parentElement.style.flexGrow = ‘1’;

    iframe.style.removeProperty(‘height’);
    iframe.style.removeProperty(‘min-height’);
    iframe.style.removeProperty(‘max-height’);

    iframe.style.flexGrow = ‘1’;
    iframe.style.flexShrink = ‘1’;
    iframe.style.flexBasis = ‘auto’;
    iframe.style.paddingBottom = ’42px’;

    var controlAddIn = document.getElementById(‘controlAddIn’);
    controlAddIn.innerHTML = ‘Hello World!’;

    CSMHTMLViewAction.js

    var GetHTMLToShow = (function () {
    function GetHTMLToShow(HTMLText) {
    iframe.innerHTML = HTMLText;
    };

    })();

    • Maybe the code on the page runs to early, before the control is even ready to receive calls? I would recommend to add a control ready event to the control and wait for it before you send any data to it.

Leave a Reply to ajk Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.