Mendix JavaScript Actions Skill
SkillWeb & browsingLets your agent create and run JavaScript actions that execute in the browser, using DOM, fetch, or geolocation.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Mendix JavaScript Actions Skill skill
About this capability
Create, call and drop JavaScript actions, client-side logic called from nanoflows, not microflows. Use when behaviour must run in the browser or on the device: DOM, fetch, geolocation, or wrapping a marketplace JS action.
What this skill tells your AI
The instructions your AI receives, as published by mendixlabs/mxcli in .claude/skills/mendix/javascript-actions/SKILL.md and read by ahel’s review.
Guidance for creating, calling, and dropping JavaScript actions in Mendix projects with MDL. JavaScript actions hold custom client-side logic and are called from nanoflows (not microflows — those use Java actions).
When to Use This Skill
- Adding client-side behaviour (browser/native APIs, DOM,
fetch, geolocation, …) - Logic that must run on the device rather than the server
- Calling an existing JavaScript action from a nanoflow
- Wrapping a marketplace/native capability exposed as a JS action
For server-side custom code, use Java actions instead (see java-actions).
Overview
A JavaScript action is two things on disk:
- The model unit (
JavaScriptActions$JavaScriptAction). - A source file
javascriptsource/<Module>/actions/<Name>.jscontaining an exportedasync function.
CREATE JAVASCRIPT ACTION writes both. The MDL body you provide becomes the
function body (between the BEGIN USER CODE / END USER CODE markers), so it
normally returns a Promise.
Syntax
CREATE [OR MODIFY] JAVASCRIPT ACTION Module.Name ( parameters )
RETURNS type
[EXPOSED AS 'caption' IN 'category']
[PLATFORM Web | Native | Hybrid | All] -- default Web
AS $$
<javascript>
$$;
DROP JAVASCRIPT ACTION Module.Name;
Clause order is fixed: returns, then exposed as, then platform, then as.
AS $$ ... $$is mandatory. Omitting the body causesno viable alternative at input '...'. Use a stub:AS $$ return Promise.resolve(false); $$.PLATFORMdefaults toWeb. UseNative,Hybrid, orAllto widen.OR MODIFYupdates an existing action in place (UUID preserved); without it, a duplicate name is an error (use create or modify to overwrite).
Parameter types
Same type system as Java actions:
- Primitives:
String,Integer,Long,Decimal,Boolean,DateTime - Entity:
Module.EntityName· List:List of Module.EntityName - Enumeration:
ENUM Module.EnumName - Type parameter (generics): declare
EntityType: ENTITY <pEntity>, then use the barepEntityfor instance parameters - Append
NOT NULLto mark a parameter required.
Examples
Simple action (Web default):
CREATE JAVASCRIPT ACTION MyFirstModule.JSA_IsOnline () RETURNS Boolean
AS $$
return Promise.resolve(navigator.onLine);
$$;
Parameters + return:
CREATE JAVASCRIPT ACTION MyFirstModule.JSA_Add (
A: Integer NOT NULL,
B: Integer NOT NULL
) RETURNS Integer
AS $$
return Promise.resolve(A + B);
$$;
Exposed toolbox action, native platform:
CREATE JAVASCRIPT ACTION MyFirstModule.JSA_ShowToast (
Message: String NOT NULL,
Duration: Integer
) RETURNS Boolean
EXPOSED AS 'Show Toast' IN 'UI'
PLATFORM Native
AS $$
console.log(Message);
return Promise.resolve(true);
$$;
Idempotent update (UUID preserved):
CREATE OR MODIFY JAVASCRIPT ACTION MyFirstModule.JSA_Add (
A: Integer NOT NULL,
B: Integer NOT NULL,
C: Integer
) RETURNS Integer
AS $$
return Promise.resolve(A + B + (C || 0));
$$;
Drop (removes the unit and the .js file):
DROP JAVASCRIPT ACTION MyFirstModule.JSA_Add;
Calling from a nanoflow
JavaScript actions are invoked with CALL JAVASCRIPT ACTION inside a nanoflow
body (arguments use Name = value):
$Sum = call javascript action MyFirstModule.JSA_Add(A = 2, B = 3);
This is the nanoflow counterpart of CALL JAVA ACTION (microflows). Use it in a
CREATE NANOFLOW ... BEGIN ... END; body.
The generated .js file
CREATE writes (and OR MODIFY rewrites) javascriptsource/<Module>/actions/<Name>.js:
// This file was generated by Mendix Studio Pro.
// ...
// BEGIN EXTRA CODE
// END EXTRA CODE
/**
* @param {number} A
* @param {number} B
* @returns {Promise.<number>}
*/
export async function JSA_Add(A, B) {
// BEGIN USER CODE
return Promise.resolve(A + B);
// END USER CODE
}
Only the code between the USER CODE / EXTRA CODE markers is preserved when
Studio Pro regenerates the file. The MDL $$ body $$ lands inside USER CODE.
Inspecting
SHOW JAVASCRIPT ACTIONS [IN Module];
DESCRIBE JAVASCRIPT ACTION Module.Name; -- re-executable MDL (signature + body)
DESCRIBE output round-trips: it re-parses as a CREATE JAVASCRIPT ACTION.
Validation Checklist
- Body present:
AS $$ ... $$;— never omit it - Body returns a
Promise(the function isasync) - Clause order:
returns→exposed as→platform→as - Required parameters marked
NOT NULL - Use
CALL JAVASCRIPT ACTIONfrom nanoflows,CALL JAVA ACTIONfrom microflows - Validate before applying:
mxcli check script.mdl
Common Errors
| Symptom | Cause | Fix |
|---|---|---|
no viable alternative at input '...' | Missing AS $$ ... $$ body | Add a body (stub return Promise.resolve(false);) |
already exists — use create or modify to overwrite | Duplicate name without OR MODIFY | Add OR MODIFY |
| Action runs nowhere / wrong client | PLATFORM too narrow | Set PLATFORM All (or the right target) |
mismatched input 'platform' | Clause out of order | Put platform after exposed as, before as |
Related Documentation
java-actions— server-side custom code (microflows)write-nanoflows— nanoflow syntax and restrictionsmxcli syntax javascript-action— quick syntax reference
Signals
- GitHub stars
- 122
- Forks
- 49
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
javascript-actions- Source
- github.com/mendixlabs/mxcli