Skip to content
Back to skills

Javascript Actions

ASecurity

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.

  • 128 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 26, 2026
ai-agentsjavascriptgojavasqlapidocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 4, 2026

npx -y skills add mendixlabs/mxcli --skill javascript-actions --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Javascript Actions?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Javascript Actions
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mendixlabs-javascript-actions/badge)](https://www.skillsdirectory.com/skills/mendixlabs-javascript-actions)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: javascript-actions
description: "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."
---

# Mendix JavaScript Actions Skill

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:

1. The model unit (`JavaScriptActions$JavaScriptAction`).
2. A source file `javascriptsource/<Module>/actions/<Name>.js` containing an
   exported `async 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

```sql
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 causes
  `no viable alternative at input '...'`. Use a stub:
  `AS $$ return Promise.resolve(false); $$`.
- **`PLATFORM`** defaults to `Web`. Use `Native`, `Hybrid`, or `All` to widen.
- **`OR MODIFY`** updates 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
  bare `pEntity` for instance parameters
- Append `NOT NULL` to mark a parameter required.

## Examples

Simple action (Web default):

```sql
mdl 1;
CREATE JAVASCRIPT ACTION MyFirstModule.JSA_IsOnline () RETURNS Boolean
AS $$
    return Promise.resolve(navigator.onLine);
$$;
```

Parameters + return:

```sql
mdl 1;
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:

```sql
mdl 1;
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):

```sql
mdl 1;
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):

```sql
mdl 1;
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`):

```sql
$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`:

```javascript
// 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

```sql
LIST 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 is `async`)
- [ ] Clause order: `returns` → `exposed as` → `platform` → `as`
- [ ] Required parameters marked `NOT NULL`
- [ ] Use `CALL JAVASCRIPT ACTION` from **nanoflows**, `CALL JAVA ACTION` from 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 restrictions
- `mxcli syntax javascript-action` — quick syntax reference

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…