ToolJet 3.0.0-LTS 页面间传参与 globals.urlparams:页面加载时读取 URL 参数的完整实战
【免费下载链接】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 中「URL 参数(URL Parameters)」在页面加载时的完整使用链路:如何通过 Switch page 事件或 JavaScript 代码把参数从上一个页面带到下一个页面,如何在目标页面通过{{globals.urlparams}}读取这些参数,并以此为依据在 On page load 事件中按条件触发 REST API 查询。读完后你可以直接复现一个「表单页携带 email 参数跳转详情页,详情页根据参数决定是否拉取数据」的典型内部工具场景,并理解其在前端源码中的实现细节。
URL 参数是什么、从哪里来
URL 参数用于在页面之间传递数据。页面以带参数的 URL 打开时,这些参数会挂载到全局对象globals下,通过{{globals.urlparams}}访问整个参数集合(键值对对象),通过{{globals.urlparams.<parameter_name>}}访问具体某一个参数。
目前 ToolJet 中向 URL 添加参数的途径有两种:
- 通过事件的Switch page(切换页面)动作,在动作配置面板中直接添加 Query params;
- 通过JavaScript 代码查询(JavaScript Code query)在代码中发起带查询参数的页面跳转。
从源码结构看,globals.urlparams的注入发生在应用数据加载 Hook 中:useAppData.js 在应用加载完成后执行
setResolvedGlobals( 'urlparams', JSON.parse(JSON.stringify(queryString.parse(location?.search))), moduleId );即使用query-string库解析当前浏览器地址栏中的location.search,把解析结果深拷贝后写入globals命名空间。这意味着任何来源(Switch page 事件、直接粘贴 URL、外部链接)写进地址栏的查询参数,最终都会以同一份对象暴露给模板表达式与 JS 查询,这也是「页面加载时可用」这一能力的底层来源。
示例场景:Home 页带参跳转 Dashboard 页
下面完整复现文档中的示例:创建一个Home页和一个Dashboard页,用户在Home页的表单里输入邮箱,点击按钮后跳转到Dashboard页,且 URL 上携带email参数;Dashboard页的加载逻辑再根据该参数决定是否执行 REST API 查询。
第一步:创建页面。新建应用后默认存在一个Home页,从左侧边栏的 Pages 菜单再创建一个名为Dashboard的页面即可。
第二步:搭建 Home 页表单。在Home页添加一个 Form 组件,其中包含一个文本输入框(命名为textinput1,用于输入邮箱)和一个按钮(命名为Submit)。
第三步:配置 Switch page 事件并添加 URL 参数。选中按钮,添加事件On click,动作选择Switch page,目标页面选择Dashboard。在动作配置面板中可以看到「Query params」区域,添加参数email,值设为{{components.form1.data.textinput1.value}}—— 即把邮箱输入框的当前值作为 URL 参数传递出去。
源码侧的实现:这个「Query params」编辑区对应 SwitchPage.jsx 面板组件,每个参数是一对[key, value],分别由两个带代码提示的输入框(CodeHinter)编辑,可增删多组。而事件真正执行时,处理逻辑位于 eventsSlice.js:
const queryParams = event.queryParams || []; if (page.restricted && mode !== 'edit') { toast.error('Access to this page is restricted. Contact admin to know more.'); } else if (!page.disabled) { const resolvedQueryParams = []; queryParams.forEach((param) => { resolvedQueryParams.push([ getResolvedValue(param[0], customVariables, moduleId), getResolvedValue(param[1], customVariables, moduleId), ]); }); // 预览模式下的 version / env 参数会被保留 const currentUrlParams = new URLSearchParams(window.location.search); ... switchPage(page.id, page.handle, resolvedQueryParams, moduleId); }两个值得注意的实现细节:
- 参数值会先经过
getResolvedValue解析——所以{{components.form1.data.textinput1.value}}这类表达式在跳转前就被求值为真实字符串,URL 上携带的是最终值; - 预览参数会被自动保留——如果当前 URL 上带有
version或env(版本预览、环境切换相关参数),且新参数列表中没有同名项,它们会被前置保留,避免页面跳转后退出预览/指定环境上下文。
另外,同一套queryParams机制也适用于跨应用跳转的 Go to app 动作(eventsSlice.js 中把解析后的参数拼接到/applications/{slug}?key=value上)。
第四步:验证参数已生效。点击Submit后,Dashboard页会以带?email=...的 URL 打开。打开左侧 Inspector,在globals下找到URL Params,即可看到email参数的键值对。
Dashboard 页:两个 REST API 查询与表格绑定
在Dashboard页添加两个 Table 组件,数据分别来自两个独立的 REST API 查询。
Query 1:products(获取商品列表)
- 新建一个 REST API 查询,命名为
products,请求一个示例 REST API:https://fakestoreapi.com/products; - 运行查询并查看 Preview 返回的数据;
- 打开
table1的属性面板,把表格数据(table data)绑定为{{queries.products.data}}。
Query 2:users(获取用户详情)
- 新建一个 REST API 查询,命名为
users,请求:https://jsonplaceholder.typicode.com/users; - 运行查询并查看 Preview 返回的数据;
- 打开
table2的属性面板,把表格数据绑定为{{queries.users.data}}。
这两个查询此刻只是「备好数据管道」,是否真正执行由下一步的 JavaScript 查询与页面加载事件共同决定。
Query 3:JavaScript 查询——读取 URL 参数并按条件触发查询
新建一个 JavaScript Code 查询,命名为urlparams。它的作用是在页面加载时轮询等待 URL 参数就绪,确认email参数存在后依次执行products与users两个 REST API 查询,参数缺失则弹出提示:
function waitForURLParams(timeout) { // Wait for URL parameters to be available const check = resolve => { // Check if URL parameters are available if (location.search.length > 0) resolve(); // URL parameters are available else setTimeout(_ => check(resolve), timeout); // Check again after a timeout } return new Promise(check); // Return a promise that resolves when URL parameters are available } async function checkAndRunQuery(timeout) { // Check if URL parameters are available and run the REST API queries await waitForURLParams(timeout); // Wait for URL parameters to be available const urlParams = new URLSearchParams(window.location.search); // Get URL parameters if (urlParams.get('email')) { // Check if email parameter is present in the URL await actions.runQuery('products'); // Run the REST API query to get products await actions.runQuery('users'); // Run the REST API query to get user details } else { alert('URL param not found'); // Alert if email parameter is not present in the URL } } checkAndRunQuery(5000); // Check if URL parameters are available and run the REST API queries after a timeout of 5 seconds代码要点:
waitForURLParams用轮询 + Promise 等待location.search非空,5000(5 秒)为每轮检查的间隔;- JS 查询上下文中可用内置的
actions.runQuery(queryName)主动执行其它查询;同理,JS 代码中也可以通过actions.switchPage发起带queryParams的页面切换(事件处理层实现了switchPage(pageHandle, queryParams)签名,见 eventsSlice.js),这就是文档所说的「从 JavaScript 代码添加 URL 参数」的途径; - 除
location/URLSearchParams外,也可以直接读取 ToolJet 暴露的globals.urlparams.email,二者在同一页面加载完成后取值一致。
On page load 事件:把整条链路串起来
最后把 JavaScript 查询挂到页面加载事件上:
- 打开左侧 Pages 菜单,展开
Dashboard页的菜单; - 选择添加 Event handler,新建一个
On page load事件,动作选择Run query,查询选择urlparams。
至此形成完整闭环:用户输入邮箱并点击Submit→ 地址栏携带email参数打开Dashboard→On page load触发urlparams查询 → JS 确认参数存在 → 执行products、users查询 → 两个表格通过{{queries.products.data}}/{{queries.users.data}}绑定自动渲染数据。
页面加载事件的源码级时序:在 useAppData.js 中,组件布局就绪且 License 校验完成后会区分两种场景:
- 首次加载:先执行
runOnLoadQueries(moduleId)(跑所有标记了 run on page load 的查询),再触发handleEvent('onPageLoad', ...); - 应用内页面切换:只触发
onPageLoad事件,跳过runOnLoadQueries——源码注释明确说明这是为了避免「查询成功事件又跳转页面」造成无限循环;需要跨页刷新数据的场景应改为在onPageLoad事件中显式触发查询。
本例把查询触发放在On page load事件里而非依赖 run on page load 标记,正好契合这一设计。
实践要点小结
- 参数「写入」靠 Switch page 事件的 Query params(或 JS 代码中的
switchPage/goToApp调用),参数值在跳转前完成表达式求值; - 参数「读取」统一走
{{globals.urlparams.<key>}},其底层是 useAppData.js 对location.search的一次性解析; - 条件化执行查询(有参数才请求、缺参数则提示)是 URL 参数最常见的用途,可配合
On page load事件实现「直达详情页按需加载」; - 预览/环境参数
version、env会在页面切换时自动保留,做版本预览时不必手动透传; - 目标页若被禁用或受限,跳转会被拦截并提示(见 eventsSlice.js),配置参数链路时需先确认页面权限状态。
以上路径均基于 ToolJet 3.0.0-LTS 文档与当前仓库源码(frontend/src/AppBuilder下的事件切片、Hook 与动作面板组件),可作为排查「参数没带过去 / 查询没执行」类问题的第一手依据。
【免费下载链接】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),仅供参考