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?
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.
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.
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!