In this video, I’m integrating a color picker from https://jscolor.com into Business Central.

Bonus content, I break the compiler.
In this video, Erik walks through the process of integrating a JavaScript-based color picker (from jscolor.com) into a Business Central page extension using AL control add-ins. Along the way, he encounters some AL compiler quirks in Visual Studio Code and demonstrates how to work through them.
The Goal: A JavaScript Color Picker in Business Central
The idea came from a viewer who was having trouble getting a JavaScript color picker to work inside Business Central. Erik decided to tackle it on video, using the popular jscolor.com color picker library, which advertises a simple two-line installation.
Setting Up the Control Add-In
The first step is to define a control add-in in AL. This is the bridge between Business Central and the JavaScript world. The control add-in declaration specifies the startup script, the external JavaScript library to load, and the events that AL code can subscribe to:
controladdin ColorPicker
{
StartupScript = 'startup.js';
Scripts = 'jscolor.js';
HorizontalStretch = true;
VerticalStretch = true;
RequestedHeight = 145;
event ControlReady();
event ColorPicked(ColorInfo: Text);
}
There are two key sections here:
- Scripts — This is like an
<script src="...">include at the top of an HTML page. It loads the jscolor library so it’s available when our startup script runs. - StartupScript — This is the script that actually executes when the control add-in’s page area is loaded. It’s where we set up the color picker and wire up events.
The RequestedHeight is set to 145 pixels to give the color picker enough room to render. Because the control add-in lives inside an iframe, the picker’s popup can’t overflow into the parent Business Central page — so we need to allocate enough vertical space up front.
The iframe Challenge
An important architectural detail: control add-ins in Business Central render inside an iframe. This means it’s essentially a web page within a web page. The color picker’s popup dialog can’t break out of the iframe boundary and overlay on top of the Business Central UI. This is why the RequestedHeight needs to be large enough to contain the fully expanded picker. Erik notes that if anyone knows a way to have the picker render on top of the parent page from within the iframe, he’d love to hear about it.
Handling Dynamically Generated HTML
Because we’re injecting HTML into the control add-in’s DOM at runtime (rather than having it present when the page first loads), the jscolor library needs a little extra help. The jscolor documentation has a section specifically about “generated HTML content” — when elements with data-jscolor attributes are added dynamically, you need to call jscolor.install() to tell the library to scan for and initialize any new color picker elements.
This is the key insight that makes everything work: insert the HTML first, then call jscolor.install().
The Startup Script
The startup script is where all the JavaScript action happens. It uses the same pattern Erik demonstrated in his dynamic HTML video — get a reference to the control add-in’s container element, inject HTML into it, and then communicate back to AL via extensibility methods:
// Color Picker
HTMLContainer = document.getElementById("controlAddIn");
update = function(picker)
{
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod("ColorPicked",[picker.toRGBAString()]);
}
HTMLContainer.insertAdjacentHTML('beforeend','<input data-jscolor="{onChange:\'update(this)\', alpha:1.0}">');
jscolor.install();
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod("ControlReady",[]);
Let’s break down what’s happening step by step:
- Get the container —
document.getElementById("controlAddIn")retrieves the HTML element that Business Central provides for the control add-in’s content. - Define the update callback — The
updatefunction takes the picker instance as a parameter and callsMicrosoft.Dynamics.NAV.InvokeExtensibilityMethodto fire theColorPickedevent back to AL, passing the selected color as an RGBA string. - Inject the input element — Using
insertAdjacentHTML, we add an<input>element with adata-jscolorattribute. The configuration JSON inside that attribute setsonChangeto call ourupdatefunction and enables the alpha channel. - Install jscolor — Since the input was dynamically added, we call
jscolor.install()to have the library discover and initialize the color picker on our new element. - Signal readiness — Finally, we fire the
ControlReadyevent to let AL know the control is initialized.
Note the escaped quotes in the data-jscolor attribute: because the entire HTML string is wrapped in single quotes in JavaScript, the single quotes inside the JSON configuration (onChange:\'update(this)\') need to be escaped with backslashes.
Using the Control Add-In on a Page
On the AL side, we create a page extension to place the color picker on the Customer Card. Note that while we define a controladdin, when we use it on a page, the keyword is usercontrol:
pageextension 55300 "Customer Card Youtube" extends "Customer Card"
{
layout
{
addafter(Name)
{
usercontrol(Color; ColorPicker)
{
ApplicationArea = All;
trigger ColorPicked(ColorInfo: Text)
begin
Message(ColorInfo);
end;
}
}
}
}
The ColorPicked trigger fires whenever the user selects a color in the picker. In this example, it simply displays the RGBA string in a message dialog — but in a real application, you could store the value in a field, apply it to styling, or use it however you need.
The Result
After deploying the extension, the Customer Card displays a fully functional color picker right below the Name field. When a color is selected, the onChange callback fires, passing the RGBA color string back to AL, which displays it in a message box — for example: rgba(255,128,0,1).
Bonus: Dealing with AL Compiler Issues
During the recording, Erik encountered a recurring issue where the AL compiler in Visual Studio Code reported that the control add-in “already exists” — even though only one definition existed. The squiggly error lines kept appearing despite the code compiling successfully. The workaround was to use Developer: Reload Window from the command palette, and in one case, completely closing and reopening Visual Studio Code. The extension compiled and deployed correctly each time despite the misleading error indicators.
Summary
To add a JavaScript color picker to Business Central:
- Download the jscolor library and add it to your extension project.
- Define a
controladdinin AL with the library as a script and a startup script for initialization. - In the startup script, dynamically inject an input element with
data-jscolorconfiguration, then calljscolor.install(). - Use a callback function with
Microsoft.Dynamics.NAV.InvokeExtensibilityMethodto pass the selected color back to AL. - Place the control on a page using
usercontroland handle the color event in an AL trigger.
The main limitation to be aware of is that control add-ins render inside an iframe, so popup elements like the color picker can’t overflow beyond the allocated space. Plan your RequestedHeight accordingly.