Build a control add-in for Business Central

Completed

To create a new control add-in, you can use the tcontroladdin snippet. A control add-in isn't an object like a table or a page, and it doesn't require an object number. A control add-in object will load one or more JavaScript files and act as a connector between the JavaScript and the AL code.

controladdin MyControlAddIn
{
    RequestedHeight = 300;
    MinimumHeight = 300;
    MaximumHeight = 300;
    RequestedWidth = 700;
    MinimumWidth = 700;
    MaximumWidth = 700;
    VerticalStretch = true;
    VerticalShrink = true;
    HorizontalStretch = true;
    HorizontalShrink = true;
    Scripts = 'script1.js', 'script2.js';
    StyleSheets = 'style.css';
    StartupScript = 'startupScript.js';
    RecreateScript = 'recreateScript.js';
    RefreshScript = 'refreshScript.js';
    Images = 'image1.png', 'image2.png';
    
    event MyEvent()
    
    procedure MyProcedure()
}

The visual aspect of a control add-in object will be created with HTML that is generated with JavaScript. You need to have some basic knowledge of HTML and Cascading Style Sheets (CSS), which are used to define the look and feel of elements on an HTML page. You can specify the color, font type and font size, paddings, and margins.

For each control add-in, Business Central will generate an Iframe element, where it will dynamically load the control. Because a control add-in is a visual element that you can insert somewhere on a page, you can set some dimension properties. You can specify the minimum and maximum height and width, but also a requested height and width.

  • RequestedHeight and RequestedWidth - The height and width that you want to get from the Iframe component. Values are in pixels.

  • MinimumHeight and MinimumWidth - The minimum height and width that your control add-in needs. If the available space would be less, then you'll get scrollbars. Values are in pixels.

  • MaximumHeight and MaximumWidth - The maximum height and width of your control add-in. Values are in pixels.

Along with the different height and width properties, you can also specify if your control add-in has the possibility to stretch or shrink horizontally and/or vertically.

  • VerticalStretch and VerticalShrink - Boolean value indicating if the control can stretch and/or shrink vertically.

  • HorizontalStretch and HorizontalShrink - Boolean value indicating if the control can stretch and/or shrink horizontally.

The StartupScript property is used to define which JavaScript file should be run on startup. You can specify other JavaScript files that you need in the Scripts property.

Scripts = 'script1.js', 'script2.js';

StartupScript = 'startupScript.js';

The scripts should be located within your AL extension. You can also load external scripts over HTTP(S). Alternatively, you can use jQuery or another JavaScript library.

Scripts = 'https://code.jquery.com/jquery-3.2.1.min.js','script1.js';

StartupScript = 'startupScript.js';

With the RecreateScript and RefreshScript properties, you can specify other JavaScript files that should be loaded and run when the page is recreated or refreshed, respectively.

The StyleSheets and Images properties can accept more than one filename, so you can split them with a comma. If you want to use images in your control add-in object, you need to add them to your extension and add the filename to the Images property.

StyleSheets = 'style.css'; Images = 'image1.png', 'image2.png','subfolder\image3.jpg';

A control add-in is a part that should be added to another page. Therefore, you can use the usercontrol keyword to load a control add-in. As with any control, you need to give your usercontrol a name and the source for your control add-in.

You can use the usercontrol name to access procedures in the control. In the following code example, the control add-in object is loaded on a card page. The MyProcedure function is part of the control and can be run by using the name of the control.

layout
{
    area(Content)
    {
        usercontrol(MyControlAddInName; MyControlAddIn)
        {

        }
    }
}

trigger OnOpenPage()
begin
    CurrPage.MyControlAddInName.MyProcedure();
end;

In a control add-in, you can define procedures and events. As shown in the following example, none of the procedures and events contain code. Procedures are used to run a function in JavaScript, so you can use this procedure to send that function from AL to JavaScript. The procedure MyProcedure needs to exist in JavaScript as well. If the function exists, it will be able to run that function because the name is the same.

controladdin MyControlAddIn
{
    Scripts = 'script1.js', 'script2.js';
    StartupScript = 'startupScript.js';
    
    event MyEvent()
    
    procedure MyProcedure()
}

In the JavaScript function, you can build your layout in HTML but with JavaScript commands. Knowledge of JavaScript is mandatory before you begin. In the subsequent example, two div elements will be created. The first div element will get a basic text, the second one will contain an image. The image should be part of your extension and defined in your control add-in. You can load that image by using a special function called GetImageResource, which is a function in the JavaScript library that Business Central loads when using control add-ins.

Every control add-in needs a start element, and you can retrieve that element by using the element with the controlAddIn ID. You can add your other HTML controls to this start element.

function MyProcedure() {
    var controlAddIn = document.getElementById("controlAddIn");

    var nameDiv = document.createElement("div");
    nameDiv.id = "nameDiv";
    nameDiv.appendChild(document.createTextNode("Enjoy Microsoft Learn!"));
    
    var imageDiv = document.createElement("div");
    imageDiv.id = "imageDiv";

    var image1 = document.createElement("img");
    image1.id = "image1";
    image1.setAttribute("src", Microsoft.Dynamics.
                                         NAV.GetImageResource("image1.png"));

    imageDiv.appendChild(image1);
    
    controlAddIn.appendChild(nameDiv);
    controlAddIn.appendChild(imageDiv);
}

A function can also retrieve parameters from AL in the JavaScript function. Because both programming languages support JSON, passing JsonObject or JsonArray parameters is simple.

AL CODE:

controladdin MyControlAddIn
{
    Scripts = 'script1.js', 'script2.js';
    StartupScript = 'startupScript.js';
    
    event MyEvent()
    
    procedure MyProcedure()
    procedure MyProcedure2(Customers: JsonArray; FinancialYear: Integer)
}
function MyProcedure2(customers, financialYear) {
    ...
}

To send data back to AL from JavaScript, or to run a function in AL, you can use events. In the following example, an event called MyEvent is defined. You can call this event from within JavaScript. Therefore, you would use InvokeExtensibilityMethod from JavaScript. You can specify the name and, optionally, some parameters. The parameters are passed as an array.

AL CODE:

controladdin MyControlAddIn
{
    Scripts = 'script1.js', 'script2.js';
    StartupScript = 'startupScript.js';
    
    event MyEvent()
    event MyEvent2(FirstName: Text)
    procedure MyProcedure()   
}
function MyProcedure() {
    Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('MyEvent', []);

    var textBox = document.createElement("input");
    textBox.name = "firstName";
    textBox.id = "firstName";
    textBox.setAttribute("type", "text");

    textBox.onblur(function(){
        Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('MyEvent2', 
                                                         [textBox.value]);    
    });   
}

To capture the passed value, you need to implement your event as a trigger on your page.

layout
{
    area(Content)
    {
        usercontrol(MyControlAddInName; MyControlAddIn)
        {
            trigger MyEvent2(FirstName: Text)
            begin 
                
            end;
        }
    }
}

trigger OnOpenPage()
begin
    CurrPage.MyControlAddInName.MyProcedure();
end;

You can create some exceptional control add-ins that perform drag-and-drop upload of files, display a calendar view, and display the warehouse floor plan with all the product locations. Thousands of JavaScript controls are available. Many of the controls contain functions that you can use to interact with those controls. You only need to create procedures in your control add-in (in AL) with the same name and parameters, and then you can directly link with those JavaScript controls.