How a control add-in works
- The AL page declares a
usercontrol(Name; "Control Add-in Name")field in its layout. - The Control Add-in object (
controls/RosterGridHAC.al) declares the JS files to load, the event names it raises (calls from AL into JS), and the procedures it exposes (calls from JS into AL). - BC injects an iframe sourcing the bundle’s HTML wrapper. The React app boots inside.
- The control’s
Scriptsproperty points at/scripts/assets/js/base.js— the Vite output.
The event contract
Outbound (React → AL)
Every call isMicrosoft.Dynamics.NAV.InvokeExtensibilityMethod(eventName, [parameters]). The AL trigger with the matching name runs, reads data from BC tables, builds a JsonArray or JsonObject, and calls a control-add-in procedure (back into JS) with the result.
Gantt-specific events (
GetProjects, CheckIfUserCanEdit, NewTask, CreateTaskPlanningLines, etc.) are also declared and fire when that screen is re-mounted.
Inbound (AL → React)
The control add-in declares procedures, which BC compiles into JavaScript callbacks that the AL page calls withCurrPage.Control.<ProcedureName>(<Args>). The React app registers each as a window.<NAME_IN_UPPER_SNAKE> function in dataService.ts.
The startup handshake
Working with the bridge in code
Bundle layout (after npm run build)
Updating the contract
When you add a new feature that needs a new event or procedure:- Add the event/procedure to
controls/RosterGridHAC.al. - Implement the AL trigger on the hosting page (
Pag70003175). - Add the matching service function in
dataService.ts. - Rebuild the React bundle (
npm run build). - Rebuild the AL
.app. - Republish.

