基于 fx 与用户组(Groups)在 ToolJet 中条件显示组件
基于 fx 与用户组Groups在 ToolJet 中条件显示组件【免费下载链接】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本文为技术文章基于仓库文档 conditionally-display-components.md 编写并结合仓库源码进行深度扩充。ToolJet 条件显示组件实战利用 fx 表达式与用户组Groups实现按角色动态渲染 UI当同一个 ToolJet 应用需要被多个用户组如 Manager、普通员工同时访问时往往需要同一份应用、不同的人看到不同的界面——例如审批按钮只对管理者可见、编辑入口只对管理员开放。本文基于 ToolJet 的Visibility 属性 fx 表达式 用户组Groups机制完整演示如何让组件按登录用户的所属组条件显示。读完本文你将掌握globals.currentUser全局对象的用法、组判断表达式的写法并能用同样的逻辑实现多组判断、角色判断以及整块区域的条件渲染。场景背景为什么需要按组控制组件可见性ToolJet 应用默认对同一工作区内的成员可见但不同成员的角色与职责可能差异巨大。以文档示例中的员工请假管理应用为例普通员工只能查看自己的请假记录、提交请求Manager 组除了查看还需要看到Approve Selected批量审批按钮来执行审批操作。如果让所有人看到审批按钮普通员工会看到无法使用的功能如果隐藏按钮Manager 又无法操作。此时就需要根据当前登录用户的所属用户组来动态决定组件是否渲染。文档中给出的目标非常明确在这个应用中Approve Selected按钮只应在Manager组的成员访问应用时显示。下面这张图展示了应用未加任何条件时的初始界面表格列出了多条请假记录右下角有Approve Selected按钮前置知识ToolJet 中的用户组Groups与全局变量在动手之前先建立两个关键概念。1. 用户组GroupsToolJet 中的组是工作区层面的权限集合。从后端源码看每个组织Organization维护一组GroupPermissions实体getAllGroupByOrganization会按organizationId查询全部组见 server/src/modules/group-permissions/util.service.ts邀请新用户时后端会把用户加入指定组并将组名汇总为groupsArray见 server/src/modules/organization-users/util.service.ts。这意味着当前用户属于哪些组是登录会话中就已确定的运行时数据前端应用可以直接读取无需额外查询接口。2.globals全局对象与currentUserToolJet 在前端维护一个名为globals的全局运行时对象应用中的所有表达式fx都可以通过{{ }}语法访问它。其中currentUser是当前登录用户信息的集合。从源码可以确认currentUser的结构与填充逻辑。在 frontend/src/AppBuilder/_hooks/useAppData.js 中前端通过setResolvedGlobals(currentUser, {...})注入用户数据setResolvedGlobals( currentUser, { ...user, groups: currentSession?.groups, role: currentSession?.role?.name, ssoUserInfo: currentSession?.ssoUserInfo, ...(currentSession?.currentUser?.metadata !isEmpty(currentSession?.currentUser?.metadata) ? { metadata: currentSession?.currentUser?.metadata } : {}), }, moduleId );由此可以确认globals.currentUser至少包含以下字段字段说明groups当前用户所属的全部组名数组如[allusers, admin, Managers]role当前用户在当前工作区的角色名称ssoUserInfo通过 SSO 登录时返回的用户信息如 OIDC 用户属性metadata用户元数据若存在其他用户基础字段用户名、邮箱、头像等关键点groups是一个字符串数组因此可以直接调用 JavaScript 数组的.includes()方法判断用户是否属于某个组——这正是本文核心表达式的原理基础。实操步骤为按钮设置基于用户组的 Visibility下面按文档步骤为一个具体按钮Approve Selected配置条件可见性。第 1 步选中目标组件在应用编辑器中点击画布上的Approve Selected按钮组件使其被选中。选中后右侧属性面板会显示该组件如button1的所有可配置属性。第 2 步定位 Visibility 属性在右侧属性面板中找到Visibility可见性属性。这是 ToolJet 所有组件通用的内置属性之一。从组件定义源码可以看到Button 组件的visibility是一个布尔类型的校验字段validation: { schema: { type: boolean } }并且默认值为{{true}}即默认总是可见见 frontend/src/AppBuilder/WidgetManager/widgets/button.js。第 3 步打开 fx 表达式编辑器Visibility 输入框右侧有一个fx切换按钮。点击它输入框会从静态开关切换为表达式模式允许你输入一段以{{ }}包裹的 JavaScript 表达式。fx 表达式在应用运行时求值其结果布尔值决定组件是否渲染。第 4 步输入组判断表达式在 fx 输入框中粘贴以下代码{{globals.currentUser.groups.includes(Manager)}}下图展示了该表达式在 Button 组件 Visibility 属性中的实际填写效果表达式解读globals.currentUser.groups当前登录用户的组名数组.includes(Manager)判断数组中是否包含字符串Manager整体结果用户属于 Manager 组时返回true显示按钮否则返回false隐藏按钮。注意表达式中的组名必须与工作区中实际创建的组名完全一致区分大小写。文档正文中写法为Manager而配套截图中出现的是Managers实际使用时请以你在工作区中创建的组名为准。效果验证不同组用户看到不同界面保存并发布应用后分别用不同组的账号登录预览验证条件渲染效果。非 Manager 用户的视角普通员工登录后globals.currentUser.groups中不包含Manager组表达式求值为false因此Approve Selected按钮被隐藏。从预览界面的 Inspector 面板可以看到该用户groups中只有allusers、admin等默认组Manager 用户的视角Manager 组成员登录后表达式求值为trueApprove Selected按钮正常显示可以进行批量审批操作对比两张截图可以直观看到表格、查看按钮等公共组件对所有人可见而审批按钮仅对 Manager 组可见——这就是同一应用、按组差异化渲染的效果。进阶扩展更多条件显示场景文档明确指出这套逻辑可以轻松迁移到更多场景。以下是在仓库能力范围内可直接套用的几种写法。1. 整块区域的条件显示使用 Container 组件如果需要对一组组件表单、卡片、操作栏等统一控制可见性不必给每个组件单独配置表达式。将相关组件全部拖入一个Container容器组件中然后只对容器设置 Visibility 表达式即可——容器内所有组件会跟随容器一起显示或隐藏。{{globals.currentUser.groups.includes(Managers)}}2. 多组判断任一组成员可见使用 JavaScript 的||运算符组合多个组判断{{globals.currentUser.groups.includes(Managers) || globals.currentUser.groups.includes(Admins)}}3. 基于角色的判断如果不需要精确到组也可以基于role字段判断{{globals.currentUser.role admin}}4. 反选排除某些组使用!取反例如非 HR 组的用户隐藏离职办理入口{{!globals.currentUser.groups.includes(HR)}}5. 与业务数据联动fx 表达式的求值环境是完整的运行时可以结合组件值、查询结果等。例如只有选择了行记录时审批按钮才可见{{globals.currentUser.groups.includes(Managers) table1.selectedRow ! undefined}}原理深挖Visibility 条件在 ToolJet 中如何工作理解底层机制有助于写出更可靠的表达式。1. 求值引擎{{ }}表达式ToolJet 的属性值支持静态值与动态表达式两种形态{{ }}包裹的内容会被解析为 JavaScript 表达式在运行时求值。Visibility 属性要求布尔值因此表达式的最终结果必须是true/false。2.globals.currentUser的来源前面已经看到currentUser由前端在应用数据加载阶段通过setResolvedGlobals(currentUser, {...})注入全局状态见 frontend/src/AppBuilder/_hooks/useAppData.js。其中groups直接取自currentSession?.groups即后端在用户会话中返回的组列表——会话建立时已确定因此同一登录用户在应用内各处的组判断结果是一致的。此外在 frontend/src/AppBuilder/_stores/slices/codeHinterSlice.js 中可以看到代码提示hint机制对globals.currentUser开头的表达式有专门处理自动映射到服务端用户上下文说明globals.currentUser是框架层一等公民级别的全局变量可放心在任意组件的 fx 表达式中使用。3. 组件默认可见性绝大多数组件的visibility默认值都是{{true}}如 Button、TagsInput、Accordion、AudioRecorder 等见 frontend/src/AppBuilder/WidgetManager/widgets/button.js 等组件定义。这意味着不配置 Visibility 的组件对所有登录用户可见只有当你显式写入条件表达式时才产生差异化显示。4. 组数据由后端维护组本身由工作区管理员在用户管理中创建和维护。后端在邀请用户、管理组织成员时都会维护用户与组的关系见 server/src/modules/group-permissions/util.service.ts 与 server/src/modules/organization-users/util.service.ts。因此本文方案本质上是后端会话中的组信息 → 前端全局对象 → 组件属性表达式的完整链路无需自行存储权限状态。注意事项与最佳实践组名大小写敏感includes(Manager)与组内实际名称必须逐字符一致建议先在用户管理页面确认组名未登录/公开访问场景如果应用以公开链接访问currentUser的groups可能为空或不包含业务组条件表达式会自然返回false组件隐藏请在设计公开页面时留意优先用 Container 批量控制涉及多个组件的组级可见性需求优先容器方案避免在多个组件上重复维护同一表达式可见性 ≠ 安全权限Visibility 控制的是显示/隐藏属于 UI 层体验优化对审批、删除等敏感操作仍应在服务端通过查询权限、组件权限如 server/src/modules/app-permissions/repositories/component-users.repository.ts 所管理的组件级权限等机制做真正的访问控制表达式保持简洁复杂逻辑建议拆解为多个布尔表达式或借助查询/变量预处理便于维护与调试。总结本文从 ToolJet 文档中的经典场景出发完整实现了按用户组条件显示组件在组件属性面板中找到Visibility属性点击fx切换到表达式模式输入{{globals.currentUser.groups.includes(Manager)}}保存发布后不同组的用户看到差异化界面。其底层依赖的是前端全局对象globals.currentUser含groups、role等会话数据与全组件通用的布尔型visibility属性默认{{true}}。同样的思路可以扩展到多组判断、角色判断、Container 整块区域控制以及与业务数据联动的组合条件让一份应用在多个用户群体之间优雅地千人千面。【免费下载链接】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),仅供参考