ToolJet RunJS(Run JavaScript Code)查询完全指南:在低代码应用中编写与执行自定义 JavaScript
【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet
Run JavaScript Code(下称 RunJS)是 ToolJet 内置的一种查询类型,允许你在应用中直接编写并执行自定义 JavaScript 代码,用于数据转换、组件属性操控、条件逻辑判断与动作触发等场景。本文以 tooljet-concepts/run-js.md 为主体骨架,结合仓库中的数据源参考文档、多个 how-to 教程与前端源码,系统讲解 RunJS 的创建流程、参数机制、Action 调用 API、内置库与外部库导入,以及基于 Geolocation API 的完整实战案例,帮助你全面掌握这一 ToolJet 高阶能力。
什么是 RunJS 查询
Run JavaScript Code查询让开发者与业务用户无需离开 ToolJet 应用构建器,就能编写并执行自定义 JavaScript 逻辑。它的典型用途包括:
- 转换查询返回的数据(例如格式化、聚合、过滤);
- 读取并动态修改其他组件的属性(例如根据条件隐藏/显示组件、更新文本内容);
- 根据特定条件触发动作(例如点击按钮后执行一串自定义逻辑);
- 生成随机数、唯一 ID 等动态值并回填到组件中。
从源码结构看,RunJS 在 ToolJet 前端被建模为一种静态数据源(static data source)kind,定义于 frontend/src/AppBuilder/QueryManager/constants.js,其展示名称为Run JavaScript code,短名JavaScript;在查询管理器的左侧数据源列表中,它同样以runjs为标识出现在 leftSidebarConstants.js 中。前端在保存与执行时会读取 RunJS 查询的options.code字段作为脚本主体(见 scriptAnalysis.ts),并对其进行语法解析分析(依赖检测、错误标注等),从而在编辑阶段就能给出静态提示。
创建 RunJS 查询
按照>alert(parameters.newAlert)
查询触发时,浏览器/应用会弹出 Alert 显示该参数值。
示例二:用参数调用另一个查询
先创建一个名为multiply的 RunJS 查询,添加参数num1(默认值10)与num2(默认值2),代码如下:
return parameters.num1 * parameters.num2;在画布上放置一个 Text 组件,将其文本设置为{{queries.multiply.data}}即可显示乘积结果。随后再创建名为callMultiply的查询,通过给run()传入对象覆盖参数默认值:
queries.multiply.run({num1: 20, num2: 7})执行callMultiply后,multiply查询会以num1=20、num2=7重新执行并返回140。这种"查询即函数"的模式让同一段逻辑可以被多处复用、传参,是构建复杂应用的常用手段。
与组件和事件交互
RunJS 的一大核心价值在于与组件进行动态交互。你可以给按钮挂载事件处理器(Event Handler),当它被点击时触发 RunJS 查询;也可以在 RunJS 代码中读取components.<componentName>.<property>来访问组件暴露的变量(例如components.table1.currentPageData),进而操控其他组件的属性。
关于组件暴露变量(Exposed Variables)的完整清单,可参阅 tooljet-concepts/exposed-variables.md;事件(Events)与事件处理器的概念见 tooljet-concepts/events.md;ToolJet 中可配置的全部动作(Actions)体系见 tooljet-concepts/actions.md。
高级功能与内置库
RunJS 支持一系列高级能力:设置/取消变量、打开或关闭模态框、复制内容到剪贴板、将用户登出等,这些通过特定的语法与函数完成。此外,RunJS 环境内置了三个库,可直接使用,无需额外导入:
| 名称 | 说明 |
|---|---|
| Moment | 日期与时间处理库(Moment.js) |
| Lodash | 实用工具函数库(提供merge、camelCase等) |
| Axios | 基于 Promise 的 HTTP 客户端,支持GET、POST、PUT/PATCH、DELETE等请求 |
需要说明的是,仓库前端代码本身也大量使用 Lodash(例如 appUtils.js 中import { merge, mergeWith, camelCase } from 'lodash'),这印证了 Lodash 是 ToolJet 前端运行环境中的常用工具库。
关于 Moment、Lodash、Axios 的详细文档,可分别参考官方文档站点(本文不展开外部链接)。接下来重点演示Axios的使用方式(详见 how-to/use-axios.md)。
使用 Axios 发起 HTTP 请求
GET 请求(以 JSONPlaceholder 免费 API 为例):
var url = "https://jsonplaceholder.typicode.com/users/1"; var data = (await axios.get(url)).data; return data代码先设置 URL 变量,再发起 GET 请求并取回响应体数据,最终通过return返回给查询结果。点击Preview即可看到 API 的响应内容。
POST 请求:
var url = "https://jsonplaceholder.typicode.com/users"; var data = axios.post(url,{ id: 11, name: "Shubhendra", username: "camelcaseguy", email: "shubhendra@tooljet.com",}) return data该 POST 请求向服务器提交用户信息,成功时服务器返回Status: 201(资源创建成功)。通过这种方式,RunJS 可以充当"无后端"场景下的 API 聚合层,把外部接口数据拉取、转换后直接喂给图表或表格组件。
从 RunJS 触发 Action:完整 API 速查
ToolJet 允许在 RunJS 查询中执行各种 Actions。以下语法与示例整理自 how-to/run-action-from-runjs.md,可作为日常开发的速查手册。
Run Query(触发查询)
两种等价写法:
queries.getSalesData.run() // replace getSalesData with your query nameawait actions.runQuery('getSalesData') // replace getSalesData with your query nameGet Query Data(获取查询结果)
触发查询后,若想立即在 RunJS 内部使用其返回值,可用getData()、getRawData()与getLoadingState():
await queries.getSalesData.run(); // replace getSalesData with your query name let value = queries.getSalesData.getData();await queries.getCustomerData.run(); //replace getCustomerData with your query name let value = queries.getCustomerData.getRawData();await queries.getTodos.run() //replace getTodos with your query name let value = queries.getTodos.getLoadingState();Set / Unset / Get 变量
创建变量:
actions.setVariable('<variableName>', `<variableValue>`)删除变量:
actions.unSetVariable('<variableName>')设置后立即读取全局变量与页面级变量:
actions.setVariable('mode','dark'); //replace mode with your desired variable name return actions.getVariable('mode');actions.setPageVariable('number',1); //replace number with your desired variable name return actions.getPageVariable('number');关于变量体系的完整概念,可参阅 tooljet-concepts/variables.md。
Logout(登出)
actions.logout();Show / Close Modal(打开/关闭模态框)
actions.showModal('<modalName>')actions.closeModal('<modalName>')Set Local Storage(写入本地存储)
actions.setLocalStorage('key', 'value');Copy to Clipboard(复制到剪贴板)
actions.copyToClipboard('<contentToCopy>')Generate File(生成文件)
actions.generateFile('<fileName>', '<fileType>', '<data>')其中fileName为文件名(字符串),fileType可选csv、plaintext或pdf,data为写入文件的数据。实际示例:
actions.generateFile('csvfile1', 'csv', '{{components.table1.currentPageData}}') // 将表格当前页数据导出为 csvfile1.csvactions.generateFile('textfile1', 'plaintext', '{{JSON.stringify(components.table1.currentPageData)}}') // 生成文本文件(数据经 JSON.stringify 序列化)actions.generateFile('Pdffile1', 'pdf', '{{components.table1.currentPageData}}') // 生成 PDF 文件Go to App(跳转其他应用)
actions.goToApp('slug',queryparams)slug可以在已发布应用的 URL 中application/之后找到,也可以在应用构建器右上角点击Share弹出的分享弹窗中获取;queryparams使用如下格式传入:[ ['key1','value1' ], ['key2','value2'] ]。
Show Alert(显示提示)
actions.showAlert('<alert type>' , '<message>' )可用的 alert 类型为info、success、warning与danger。示例:
actions.showAlert('error' , 'This is an error' )一次运行多个 Action
在 RunJS 中串联多个动作时,必须使用async-await。下面示例每隔 5 秒依次执行两个查询并弹出信息提示(完整版见 how-to/run-query-at-specified-intervals.md):
actions.setVariable('interval',setInterval(countdown, 5000)); async function countdown(){ await queries.restapi1.run() await queries.restapi2.run() await actions.showAlert('info','This is an information') }上述各类 Action 的详细参考文档位于 actions 目录,例如 show-alert.md、set-variable.md、generate-file.md 等,均可在 RunJS 中按上述方式调用。
导入外部 JavaScript 库
除内置库外,RunJS 还支持通过 CDN 动态导入任意第三方 JavaScript 库(详见 how-to/import-external-lib-js.md)。推荐到 jsDelivr 查找开源项目的 CDN 链接。
导入步骤:
- 从 ToolJet Dashboard 新建应用;
- 在查询面板选择默认的JavaScript数据源创建 RunJS 查询;
- 在代码编辑器中粘贴以下代码(示例同时导入 MathJS 与 FlattenJS):
// Function to add script dynamically function addScript(src) { return new Promise((resolve, reject) => { const scriptTag = document.createElement('script'); scriptTag.setAttribute('src', src); scriptTag.addEventListener('load', resolve); scriptTag.addEventListener('error', reject); document.body.appendChild(scriptTag); }); } try { // Importing MathJS await addScript('https://cdn.jsdelivr.net/npm/mathjs@11.7.0'); // Importing FlattenJS await addScript('https://cdn.jsdelivr.net/npm/flattenjs@2.1.3/lib/flatten.min.js'); // Showing a success alert await actions.showAlert("success", 'Mathjs and Flatten imported'); } catch (error) { console.error(error); }- 点击Run运行,应弹出 "Mathjs and Flatten imported" 成功提示。
:::tip 勾选查询设置中的Run this query on application load?选项,可在应用加载完成后立即使这些库全局可用。 :::
应用示例 1:用 FlattenJS 展平嵌套 JSON
return flatten({ key1: { keyA: 'valueI' }, key2: { keyB: 'valueII' }, key3: { a: { b: { c: 2 } } } });应用示例 2:用 MathJS 做数学计算
return math.atan2(3, -3) / math.pi;在查询管理器中预览输出,或在查询面板点击Run查看结果。
实战案例:用 RunJS + Geolocation API 获取用户位置
下面通过 how-to/access-users-location.md 的完整流程,演示 RunJS 与浏览器 Geolocation API 结合的真实场景(该 API 通过 GPS、Wi-Fi、IP 定位等手段提供经纬度、海拔、速度等地理数据;出于隐私考虑,浏览器会在定位前请求用户授权)。
- 新建一个应用;
- 进入应用编辑器,在底部查询面板点击+ Add,数据源选择Run JavaScript Code创建 RunJS 查询;
- 编写以下代码调用 Geolocation API:
function getCoordinates() { // Function to get coordinates return new Promise(function (resolve, reject) { // Promise to get coordinates navigator.geolocation.getCurrentPosition(resolve, reject); // Get current position }); } async function getAddress() { // Function to get address const position = await getCoordinates(); // Await the coordinates let latitude = position.coords.latitude; // Get latitude let longitude = position.coords.longitude; // Get longitude return [latitude, longitude]; // Return the coordinates } return await getAddress(); // Return the address- 在查询编辑器下方的Settings中勾选
Run this query on application load?,确保应用每次打开都自动获取位置; - 点击Run,浏览器会弹出位置授权提示,允许后即可获得坐标;
- 查询成功后,坐标会显示在查询编辑器的Preview区;也可以在左侧边栏的Inspector中展开
queries -> runjs1 -> data查看返回结果; - 将坐标用于Map(地图)组件:向画布添加 Map 组件,在其Initial location属性中填入:
{{ {"lat": queries.runjs1.data[0], "lng": queries.runjs1.data[1]} }}- 更新属性后,地图组件即会显示用户当前位置。
这个案例很好地展示了 RunJS 的完整链路:浏览器原生能力(Geolocation)→ RunJS 查询 → 查询结果暴露为queries.*.data→ 组件属性绑定 → 可视化呈现。
调试与错误处理
RunJS 也支持刻意制造异常以辅助调试(详见 how-to/intentionally-fail-js-query.md):
- 在查询面板点击+ Add新建 RunJS 查询;
- 在编辑器中粘贴以下代码,利用
ReferenceError构造函数主动抛出错误:
throw new ReferenceError('This is a reference error.');- 为该查询添加事件处理器(Event Handler),在查询**失败(failure)**时触发 Alert 等动作;
- 点击Run观察错误被抛出并触发失败处理逻辑。
这种"失败路径演练"可以验证应用的容错与兜底机制,提升整体健壮性。
从源码看 RunJS 的实现原理
结合前端源码,可以更深入理解 RunJS 在 ToolJet 中的实现定位:
- 静态数据源建模:
runjs与runpy、tooljetdb同属于静态数据源(static data sources),见 QueryManagerBody.jsx;且 RunJS 查询不支持中止(abort)操作,ABORT_UNSUPPORTED_KINDS集合包含runjs(见 constants.js)。 - 脚本静态分析:前端会对 RunJS 的
options.code进行解析分析(analyzeScript),并基于options对象做 WeakMap 缓存;查询保存会替换 options,从而自动失效缓存(见 scriptAnalysis.ts)。这意味着编辑器能够在运行前就识别脚本中的依赖与潜在问题。 - 查询面板集成:查询面板切片对
runjs类型的查询有专门处理逻辑(见 queryPanelSlice.js),说明 RunJS 与查询运行状态、依赖变更检测深度绑定。
这些实现细节印证了 RunJS 并非简单的"文本执行器",而是与查询管理器、依赖分析、事件系统深度集成的第一等公民能力。
更多参考资料
- 查询(Queries)基础概念:tooljet-concepts/queries.md
- RunJS 查询的完整参考(参数、示例查询、内置库):data-sources/custom-js.md
- 从 RunJS 执行动作:how-to/run-action-from-runjs.md
- 在 RunJS 中使用 Axios:how-to/use-axios.md
- 导入外部库:how-to/import-external-lib-js.md
- 获取用户位置:how-to/access-users-location.md
- 定时触发查询:how-to/run-query-at-specified-intervals.md
- 刻意制造查询失败:how-to/intentionally-fail-js-query.md
【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考