ToolJet「Go to app」动作完全指南:事件驱动跨应用跳转与查询参数传递
【免费下载链接】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
导读
「Go to app」是 ToolJet 提供的一个导航类动作(Action),用于在某个事件发生时,将用户跳转到任意一个**已发布(released)**的 ToolJet 应用。本文基于 ToolJet 2.50.0-LTS 版本文档与源码,完整讲解该动作的配置方式(目标应用选择、查询参数、Debounce 防抖)、底层执行原理(事件分发、目标解析、URL 拼接)、在编辑器与运行器中的差异行为,以及如何在 JavaScript 代码(RunJS)中调用等价能力,帮助你搭建应用之间的无缝导航链路。
动作概览:从一个应用跳到另一个应用
「Go to app」的核心定位是应用级导航:与「Switch page」在同一应用内切换页面不同,它会将用户带到另一个 ToolJet 应用。官方文档明确了使用前提——只有已发布(released)的应用才能通过该动作打开:
This action allows you to open any released ToolJet application when an event occurs. Only the apps that are released can be opened using this action.
这意味着目标应用必须先经历「发布/Release」流程,否则跳转目标无法被解析。这一点与源码中的校验逻辑完全一致(详见后文「目标应用有效性校验」一节)。
在 ToolJet 前端源码中,该动作被登记为导航组(navigation group)的一员。见 ActionTypes.js:
{ name: 'Go to app', id: 'go-to-app', options: [ { name: 'app', type: 'text', default: '' }, { name: 'queryParams', type: 'code', default: '[]' }, ], group: 'navigation', },从定义可以看出,该动作只有两个核心配置项:目标应用(app)与查询参数(queryParams,默认空数组),所属分组为导航类动作。同时,在 actions.js 中,goToApp被列入应用构建器可用的代码提示(code hints)动作列表,说明它既可以通过可视化事件配置器使用,也可以在 RunJS 中以编程方式调用。
配置步骤:在事件处理器中绑定「Go to app」
1. 选择触发事件
在右侧检查器(Inspector)面板中,为组件(如按钮 Button)添加一个事件处理器,例如「On click」,随后在动作(Action)下拉框中选择Go to app。这是最典型的用法:用户点击按钮后跳转到另一个应用。
2. 选择目标应用
在动作选项(Action Options)区域,通过App下拉选择框从当前工作区的应用列表中选择目标应用。源码中该下拉框通过getAllApps()动态加载应用列表(见 GotoApp.jsx):
useEffect(() => { getAllApps() .then(setAppOptions) .finally(() => setIsLoading(false)); }, []);选中应用后,配置面板持久化的是应用的稳定标识correlationId,而不再使用传统的slug(见 GotoApp.jsx):
// Persist only the stable id; drop the legacy `slug` key. handlerChanged(eventIndex, { correlationId: value, slug: undefined }); // Mirror both `slug` and `currentVersionId` into the store so click-time URL // building works without a reload AND the validator can distinguish "missing target" from "no released version". upsertLinkedApp( value, { slug: selected?.slug ?? null, currentVersionId: selected?.currentVersionId ?? null }, moduleId );选择应用的同时,配置面板会把目标应用的slug与currentVersionId镜像写入 store 的linkedApps映射中(appSlice.js),以便在运行时无需重新加载即可拼接跳转 URL,同时为后面的有效性校验提供依据。
3. 添加查询参数(Query params)
「Go to app」支持在跳转 URL 上携带查询参数,用于向目标应用传递数据。配置面板默认展示空的参数列表,你可以通过Add param按钮添加键值对(见 GotoApp.jsx):
<Button onClick={addQueryParam}> Add param </Button>每个参数由「键」和「值」两个输入框组成,且两个输入框都支持 ToolJet 表达式(通过 CodeHinter 编辑器),这意味着你可以写入类似{{globals.currentUser.email}}或{{components.table1.selectedRow.id}}这样的动态引用(见 GotoApp.jsx)。参数值会在动作执行时被解析为实际值,再拼接到目标 URL 上。
4. 设置 Debounce 防抖(可选)
Debounce 字段默认为空。你可以输入一个毫秒数值(例如300),指定事件触发后延迟多久才执行该动作。这在防止高频事件(如快速连点按钮)造成重复跳转时非常实用。
Debounce 的实现位于事件分发层的executeAction上,源码中使用debounce包裹了动作执行函数(见 eventsSlice.js):
executeAction: debounce((eventObj, mode, customVariables = {}, moduleId = 'canvas') => { ... }),因此只要在事件配置中填写了 Debounce 毫秒值,对应动作的执行就会按该延迟节流。
提示:Debounce 字段留空表示不防抖,事件触发后立即执行动作。
5. 条件执行(Run Only If)
与 ToolJet 其他动作一致,「Go to app」也支持Run Only If条件表达式。只有当该表达式求值为真时,动作才会真正执行,适合做权限控制或前置条件判断(例如仅在选中了某行数据时才允许跳转)。
运行原理:事件是如何被分发并执行跳转的
「Go to app」的执行入口是事件分发器executeAction,它根据actionId匹配到go-to-app分支。核心执行逻辑位于 eventsSlice.js,可拆解为以下几步:
第一步:解析目标应用的 slug
执行逻辑区分两种来源(见 eventsSlice.js):
if (event.source === 'app-action') { // RunJS app action go-to-app still send a slug directly for backward compatibility. if (!event.slug) { throw new Error('No application slug provided'); } slug = getResolvedValue(event.slug, customVariables, moduleId); } else { // Builder-configured go-to-app events resolve the target via correlationId. if (!event.correlationId) { throw new Error('No application selected'); } const linkedApps = get().appStore.modules[moduleId]?.linkedApps; const appSlug = linkedApps?.[event.correlationId]?.slug; ... slug = getResolvedValue(appSlug, customVariables, moduleId); }- 通过可视化事件配置器创建的动作(
source非app-action),会基于持久化的correlationId到linkedApps映射中反查slug; - 通过 RunJS 调用的动作(
source === 'app-action'),为了向后兼容,仍然直接传递slug。
第二步:解析查询参数
查询参数以键值对数组形式存储,执行时逐个把键和值通过getResolvedValue解析为真实值,再合并为对象(见 eventsSlice.js):
const queryParams = event.queryParams?.reduce( (result, queryParam) => ({ ...result, ...{ [getResolvedValue(queryParam[0], customVariables, moduleId)]: getResolvedValue( queryParam[1], customVariables, moduleId ), }, }), {} );第三步:拼接 URL 并执行跳转
目标 URL 格式为/applications/${slug},若存在查询参数,则通过serializeNestedObjectToQueryParams序列化后以?拼接(见 eventsSlice.js):
let url = `/applications/${slug}`; if (queryParams) { const queryPart = serializeNestedObjectToQueryParams(queryParams); if (queryPart.length > 0) url = url + `?${queryPart}`; } const path = getSubpath(); if (path) url = path + url; if (mode === 'view') { window.open(url, '_self'); } else { if (confirm('The app will be opened in a new tab as the action is triggered from the editor.')) { window.open(urlJoin(getHostURL(), url)); } }最终生成的 URL 形如/applications/<slug>?key1=value1&key2=value2,其中查询参数键值可以是嵌套结构(会被序列化为 URL 查询字符串)。
编辑器与运行器中的行为差异
「Go to app」在编辑器(editor)与运行器(viewer/已发布应用)中的跳转方式不同,这是使用时需要注意的关键差异:
| 运行模式 | 跳转行为 |
|---|---|
| 运行器(view 模式) | 使用window.open(url, '_self')在当前标签页打开目标应用 |
| 编辑器(编辑模式) | 弹出确认框「The app will be opened in a new tab as the action is triggered from the editor.」,确认后在新标签页打开 |
此外,在编辑模式下,如果目标应用缺失或未发布,会抛错并通过logError('go_to_app', ...)记录到调试器(debugger),方便开发者定位问题(见 eventsSlice.js);而在运行器模式下则会跳过校验、直接尝试重定向,交给既有的 404 / 「not found」处理逻辑兜底(见 eventsSlice.js 中的注释说明)。
目标应用有效性校验:未发布应用无法跳转
前文提到「只有已发布的应用才能打开」,这一约束在源码中有明确的校验实现。校验函数isLinkedAppValid定义在 utils.js:
export function isLinkedAppValid(correlationId, linkedAppsMap) { if (!correlationId) return { isValid: true, errorMessage: null }; const entry = linkedAppsMap?.[correlationId]; if (!entry || !entry.slug) { return { isValid: false, errorMessage: `App ${correlationId} undefined. Check if the linked app exists and has a released version.`, }; } if (!entry.currentVersionId) { return { isValid: false, errorMessage: 'Check if the linked app has a released version.', }; } return { isValid: true, errorMessage: null }; }校验逻辑分两层:
- 目标应用是否存在:若
linkedApps映射中找不到对应的correlationId或没有slug,则判定无效,错误信息提示「检查目标应用是否存在且有已发布版本」; - 目标应用是否已发布:若映射中存在应用但缺少
currentVersionId(即没有已发布的版本),则判定无效,错误信息提示「检查目标应用是否有已发布版本」。
该校验在事件配置阶段(EventManager.jsx)和编辑模式执行阶段(eventsSlice.js)都会被调用。在事件管理器中,校验失败时会在事件行内展示内联错误提示(如「Undefined app」及具体错误信息),帮助你在保存前就发现配置问题。
在 JavaScript 代码(RunJS)中调用
除了通过可视化事件配置器,你也可以在RunJS代码中触发「Go to app」动作。ToolJet 的 RunJS 中暴露了actions.goToApp()方法,其签名与实现位于 eventsSlice.js:
const goToApp = (slug = '', queryParams = []) => { const event = { actionId: 'go-to-app', source: 'app-action', slug, queryParams, }; return executeAction(event, mode, {}, moduleId); };对应的方法定义如下:
goToApp(slug, queryParams)slug(字符串):目标应用的 slug(应用唯一标识)。queryParams(数组):查询参数列表,元素为[key, value]形式的二元数组。
示例:在 RunJS 中跳转到 slug 为analytics-dashboard的应用,并携带userId与source两个查询参数:
await actions.goToApp('analytics-dashboard', [ ['userId', '{{globals.currentUser.id}}'], ['source', 'homepage'], ]);执行时,该方法构造actionId: 'go-to-app'、source: 'app-action'的事件对象并走同一个executeAction分发管道。由于source为app-action,运行时直接使用传入的slug而不依赖linkedApps映射(见 eventsSlice.js),因此通过 RunJS 调用时只需保证 slug 正确即可。
其他交互方式(如 RunJS 代码中触发任意事件动作)的通用写法,可参考 run-actions-from-runjs 文档。
常见使用场景与注意事项
典型场景
- 工作台/门户导航:主应用作为工作台,点击某个业务入口按钮跳转到对应的已发布子应用;
- 上下文传递:跳转时通过查询参数把当前选中记录的主键、用户信息等传给目标应用,让目标应用直接进入对应详情页或过滤后的列表;
- 流程串联:一个应用中完成某步操作后(如表单提交成功事件),自动跳转到下一个处理环节的应用。
注意事项
- 目标应用必须先发布:未发布的应用无法作为跳转目标,配置阶段与执行阶段都会给出校验错误提示;
- 查询参数键值支持表达式:键和值都可以写 ToolJet 表达式,会在执行时动态解析,适合传递运行时数据;
- Debounce 默认关闭:需要防抖时自行填写毫秒值;
- 编辑器与运行器跳转方式不同:编辑器内跳转会弹出确认框并在新标签页打开,运行器中则直接在当前标签页跳转;
- 通过 RunJS 调用时直接传 slug:
actions.goToApp(slug, queryParams)中slug为目标应用的 slug,queryParams为[key, value]二元数组列表。
配置界面一览
下图展示了 ToolJet 中「Go to app」动作的完整配置界面(图片来源于本仓库文档 gotoapp3.png):
界面左侧为动作配置区:顶部依次是事件(Event,如 On click)、动作(Action,已选择 Go to app)与 Run Only If 条件输入框;下方的 Action Options 包含目标应用下拉选择框(App)、可增删的查询参数键值对(Query params)以及 Debounce 防抖输入框。右侧为组件属性区(如按钮文本、加载状态、事件绑定列表等),两者联动即可完成「点击按钮 → 跳转到已发布应用并携带参数」的完整配置。
【免费下载链接】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),仅供参考