ToolJet RunJS 查询执行 Actions 完整指南:从运行查询到文件生成与多动作编排
【免费下载链接】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
在 ToolJet 应用构建器中,RunJS 查询允许你在 JavaScript 代码片段里直接调用平台内置的 Actions,从而把"查询触发、变量管理、弹窗控制、文件导出、页面跳转、消息提示"等能力统一编排进一段脚本逻辑中。本指南以 ToolJet 2.50.0-LTS 官方文档 run-action-from-runjs 为主线,逐条讲解每种 Action 的调用语法与典型示例,并结合仓库前端源码(如 eventsSlice.js)说明底层实现与边界条件。读完本文,你将能在 RunJS 查询中熟练完成查询联动、变量读写、弹窗/提示、文件生成、应用跳转以及 async-await 多动作编排等实战操作。
一、RunJS 查询与 Actions 的对应关系
ToolJet 的 App Builder 在可视化层面把交互能力抽象为一组"事件动作(Actions)",它们既可以在组件事件面板中通过表单配置,也可以在 RunJS / RunPy 查询中通过代码直接调用。在仓库中,这一组动作被统一定义在两处:
- ActionTypes.js:事件面板里可选的 Action 列表,包含
run-query、show-alert、show-modal、set-custom-variable、go-to-app、generate-file等; - constants/actions.js:代码编辑器提示(code hints)中暴露给用户的 Actions 函数名清单,即
ACTIONS数组。
两处形成一一对应的关系:面板上配置的run-query对应代码中的actions.runQuery(),set-custom-variable对应actions.setVariable()。RunJS 查询本质上就是把这段 JS 代码注入到执行上下文,从而复用同一套executeAction事件分发机制(见 eventsSlice.js)。
在编写代码时,你可以选择两种风格:
- 全局查询对象风格:
queries.<查询名>.run(),每个查询对象由 queryPanelSlice.js 动态构建; actions命名空间风格:actions.runQuery('<查询名>'),直接调用事件分发。
二、运行查询(Run Query)
2.1 两种调用语法
queries.getSalesData.run() // replace getSalesData with your query name或等价的 actions 风格:
await actions.runQuery('getSalesData') // replace getSalesData with your query name从源码看,queries.<name>.run(params, callbackFns)内部会对params做对象校验(非对象会被归一为空对象),并按查询定义的options.parameters过滤出合法参数后调用actions.runQuery(见 queryPanelSlice.js)。而actions.runQuery(queryName, parameters, moduleId, callbackFns)会按名称在当前模块的查询列表中查找目标查询,并构造{ actionId: 'run-query', queryId, queryName, parameters, callbackFns }事件交由executeAction执行(见 eventsSlice.js)。
需要留意两个边界条件(源码中有明确处理):
- 若查询名称不存在,会弹出
Query not found错误提示; - 若在查询自身的代码中调用自身(
queryId === query?.id),会弹出Cannot run query from itself提示,防止无限递归(见 eventsSlice.js)。
2.2 带参数运行
当目标查询定义了参数时,传入的参数会被query.options.parameters逐个过滤,只保留声明过的参数名(见 eventsSlice.js):
await actions.runQuery('getUserById', { id: components.dropdown1.selectedValue });三、获取查询结果数据(Get Query Data)
触发查询后若想立即在 RunJS 中使用其返回结果,可在await queries.<name>.run()之后调用以下三个函数,它们由 queryPanelSlice.js 以"实时 getter"方式提供:
| 函数 | 返回值 | 对应底层字段 |
|---|---|---|
getData() | 查询处理后的数据 | resolvedState中该查询的data |
getRawData() | 查询的原始响应数据 | 该查询的rawData |
getLoadingState() | 查询是否处于加载中 | 该查询的isLoading |
// 触发查询并读取数据 await queries.getSalesData.run(); let value = queries.getSalesData.getData();// 触发查询并读取原始数据 await queries.getCustomerData.run(); let value = queries.getCustomerData.getRawData();// 触发查询并读取加载状态 await queries.getTodos.run() let value = queries.getTodos.getLoadingState();源码中注释明确说明这些 getter 是"live getter":在await queries.x.run()完成后,任何字段(data、error、request、response、metadata、responseHeaders等)都会反映本次运行的最新结果(见 queryPanelSlice.js)。因此getData()/getRawData()必须放在await ...run()之后调用,才能拿到刚运行完的数据,否则读到的是上一次(或空)的状态。
四、变量管理:设置、删除与读取
4.1 设置变量(Set Variables)
actions.setVariable('<variableName>', `<variableValue>`)源码中setVariable(key, value)会校验 key 非空,随后构造actionId: 'set-custom-variable'事件(见 eventsSlice.js)。
4.2 删除变量(Unset Variable)
actions.unSetVariable('<variableName>')对应事件为unset-custom-variable,key 为空时直接忽略(见 eventsSlice.js)。另外还提供了批量删除actions.unsetAllVariables(),对应unset-all-custom-variables(见 eventsSlice.js)。
4.3 读取变量(Get Variables)
设置变量后如需在同一段 RunJS 代码内立刻取回,使用getVariable与getPageVariable:
// 设置并读取普通变量 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');页面级变量的对应实现为setPageVariable(key, value)→set-page-variable与getPageVariable(key)→get-page-variable(见 eventsSlice.js)。它们与普通变量的区别在于作用域:普通变量在整个应用生命周期内有效,页面变量随页面切换而隔离或清空。
五、用户会话与界面控制
5.1 登出(Logout)
actions.logout();实现上构造actionId: 'logout'事件,最终调用logoutAction()(来自@/AppBuilder/_utils/auth)完成当前用户登出(见 eventsSlice.js)。适合在"退出登录"按钮的 onClick 事件中通过 RunJS 触发。
5.2 打开 / 关闭弹窗(Show / Close Modal)
actions.showModal('<modalName>') actions.closeModal('<modalName>')源码中showModal(modalName)会在当前组件树中按组件名称(component.name === modalName)查找 Modal 组件的实例 id,再构造show-modal/close-modal事件(见 eventsSlice.js)。因此参数必须与画布上 Modal 组件的名称完全一致,否则找不到对应弹窗。
5.3 设置本地存储(Set Local Storage)
actions.setLocalStorage('key', 'value');对应set-localstorage-value事件(见 eventsSlice.js)。数据写入浏览器localStorage,可在不同页面、甚至重新打开应用后读取,适合存放主题偏好、用户设置等轻量持久化数据。
5.4 复制到剪贴板(Copy to Clipboard)
actions.copyToClipboard('<contentToCopy>')实现上构造copy-to-clipboard事件,最终调用copyToClipboard(来自@/_helpers/appUtils)执行复制(见 eventsSlice.js)。注意浏览器对剪贴板 API 的调用往往要求用户手势(如点击按钮)上下文,在 RunJS 中同步调用通常没有问题。
六、生成文件(Generate File)
6.1 语法与参数
actions.generateFile('<fileName>', '<fileType>', '<data>')| 参数 | 说明 | 可选值/类型 |
|---|---|---|
fileName | 生成文件的名称 | 字符串 |
fileType | 文件类型 | csv、plaintext、pdf |
data | 写入文件的数据 | 任意数据,可用{{ }}引用组件/查询值 |
源码中对三个参数做了非空校验,任一缺失都会弹出错误提示Action failed: fileName, fileType and data are required,并构造generate-file事件(见 eventsSlice.js)。
6.2 生成 CSV 文件
actions.generateFile('csvfile1', 'csv', '{{components.table1.currentPageData}}') // generate a csv file named csvfile1 with the data from the current page of table6.3 生成文本文件
actions.generateFile('textfile1', 'plaintext', '{{JSON.stringify(components.table1.currentPageData)}}') // generate a text file named textfile1 with the data from the current page of table (stringified)文本格式下建议先用JSON.stringify()将对象数组序列化为字符串,否则写入内容可能不符合预期。
6.4 生成 PDF 文件
actions.generateFile('Pdffile1', 'pdf', '{{components.table1.currentPageData}}') // generate a text file named Pdffile1 with the data from the current page of table文件生成的底层逻辑由@/_lib/generate-file提供(见 eventsSlice.js)。这一动作非常适合"一键导出报表/表格数据"场景,例如把表格当前页数据导出为 CSV 供下载。
七、应用间跳转(Go to App)
actions.goToApp('slug', queryparams)两个参数的含义:
slug:目标应用的 slug。可以在已发布应用的 URL 中application/之后找到,也可以在 App Builder 右上角点击Share按钮弹出的分享弹窗中获取;queryparams:以二维数组形式提供的查询参数,格式为[ ['key1','value1' ], ['key2','value2'] ]。
actions.goToApp('sales-dashboard', [['period', '2026-Q3'], ['region', 'APAC']]);实现上构造actionId: 'go-to-app'事件并携带slug与queryParams(见 eventsSlice.js)。在事件面板中,该动作对应go-to-app(见 ActionTypes.js)。目标应用收到参数后可通过globals.urlparams读取。
八、消息提示(Show Alert)
actions.showAlert('<alert type>' , '<message>' )可用提示类型:info、success、warning、danger。
示例:
actions.showAlert('error' , 'This is an error' )对应show-alert事件,参数为alertType与message(见 eventsSlice.js)。提示会以顶部/角落的 Toast 形式展示,适合在分支逻辑中给出成功或失败反馈。注意官方示例中使用了'error',而标准可选值集合为info/success/warning/danger,实际使用建议从标准集合中选取以保证样式符合预期。
九、组合使用:async-await 编排多个动作
在 RunJS 查询中运行多个动作时,必须使用async-await来保证顺序执行,否则后续动作会在前序查询尚未完成时就启动。
典型示例:按 5 秒间隔轮询两个查询,并在每次完成后弹出信息提示:
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') }这里的setInterval每 5 秒调用一次countdown,await确保restapi1→restapi2→ 提示按顺序完成。如果你需要更精细的"定时/间隔运行查询"能力,可进一步参考仓库中的完整指南 run-query-at-specified-intervals。
十、补充:更多可用动作与排查建议
除了文档列出的动作,ACTIONS常量(见 constants/actions.js)中还暴露了以下能力,可在 RunJS 中按同样风格调用:
| 函数 | 作用 |
|---|---|
actions.resetQuery('<查询名>') | 重置查询状态(对应reset-query) |
actions.abortQuery('<查询名>') | 中止正在运行的查询(对应abort-query) |
actions.switchPage('<页面名>') | 切换当前应用页面 |
actions.logInfo(...)/actions.logError(...) | 向调试器输出日志 |
actions.toggleAppMode('<模式>') | 切换应用的编辑/查看模式 |
actions.scrollComponentInToView(...) | 将组件滚动到可视区域 |
排查建议:
- 查询名写错:
runQuery找不到查询时会提示Query not found,请核对查询面板中的名称(区分大小写); - 自调用:不要在 RunJS 查询里运行它自己,否则提示
Cannot run query from itself; - Modal 名称不匹配:
showModal/closeModal按组件名称精确匹配,请确认传入的名称与画布组件名一致; - 数据时序:
getData()等读取函数必须在await ...run()之后调用; - 代码提示:编辑器内输入
actions.或queries.时会基于ACTIONS常量与查询对象实时给出函数提示,可减少拼写错误(见 codeHinterSlice.js)。
相关文档
- 官方指南原文:run-action-from-runjs
- Actions 列表定义:ActionTypes.js
- Actions 代码提示常量:constants/actions.js
- Actions 核心实现:eventsSlice.js
- 查询对象(
run/getData/getRawData/getloadingState)实现:queryPanelSlice.js
【免费下载链接】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),仅供参考