☰
ToolJet Table 组件服务端过滤(Server Side Filter)完整实现指南
2026/10/15 18:59:16 网站建设 项目流程

ToolJet Table 组件服务端过滤(Server Side Filter)完整实现指南

【免费下载链接】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 的Table组件上实现服务端(Server Side)过滤操作:通过开启serverSideFilter属性、用 RunJS 动态拼接 SQL、借助事件处理器将过滤器变化回传到数据库查询,让过滤作用于全量数据集而非当前已加载到前端的记录。读完本文,你将掌握从组件配置、查询编排到事件链路的完整实操方案,并能理解其背后的前端源码实现原理。

为什么需要服务端过滤

在 ToolJet 的 Table 组件中,过滤既可以在客户端完成,也可以在服务端完成,二者适用于不同场景(可参考 serverside-operations 概览):

维度服务端操作客户端操作
执行位置服务器(数据库)用户浏览器/应用
适用场景大型数据集、安全与数据完整性要求高、复杂业务逻辑实时交互、降低服务器负载、离线能力
性能表现仅返回过滤后的结果,加载更快、扩展性更好需先将全部数据拉取到本地再处理,大数据集下可能出现性能问题

服务端过滤的核心价值在于:过滤条件在服务器端执行,影响的是数据集中的全部记录,而不是 Table 组件当前已加载的那一小部分数据。这一点也得到源码佐证——在 useTable.js 中,当开启服务端模式时,Table 底层使用的 TanStack Table 会切换为manualFiltering模式,即过滤逻辑完全交由开发者通过查询在服务端处理,前端不再对已加载数据做本地过滤。

前置准备:添加 Table 组件并填充数据

在实现过滤之前,先完成 Table 组件与数据源的准备工作:

  1. 从右侧组件库中拖拽一个Table组件到画布上。
  2. 在底部查询面板中选择数据源并创建新查询。本指南以 ToolJet 内置的示例数据源(Postgres)为例,使用如下查询获取数据:
SELECT * FROM public.sample_data_orders LIMIT 100
  1. 将 Table 组件的Data属性值设置为{{queries.<query_name>.data}},让组件展示查询返回的数据。

第一步:开启 Server Side Filter 属性

在 Table 组件的属性面板中找到Server Side Filter开关并将其启用。

从源码可以确认该开关的实际行为:在 widgets/table.js 中,serverSideFilter被定义为一个clientServerSwitch类型的属性,用于在客户端/服务端两种过滤模式间切换;其默认值为{{false}}(见 widgets/table.js),并在 initSlice.js 中初始化。开启后,Table 的useTableHook 会将该值映射为 TanStack Table 的manualFiltering: serverSideFilter(见 useTable.js),从而关闭前端自动过滤。

第二步:创建 RunJS 查询动态生成 SQL

开启服务端过滤后,Table 组件会把当前过滤器列表暴露为components.table1.filters变量。创建一个RunJS查询,读取该变量并动态拼接出带过滤条件的 SQL:

const filterData = components.table1.filters; const createSQLQueries = (filters) => { let conditions = ''; filters.forEach(({ condition, value, column }, index) => { const prefix = index === 0 ? 'WHERE' : 'AND'; switch (condition) { case "contains": conditions += ` ${prefix} ${column} ILIKE '%${value}%'`; break; case "doesNotContains": conditions += ` ${prefix} ${column} NOT ILIKE '%${value}%'`; break; case "matches": case "equals": conditions += ` ${prefix} ${column} = '${value}'`; break; case "ne": conditions += ` ${prefix} ${column} != '${value}'`; break; case "nl": conditions += ` ${prefix} ${column} IS NULL`; break; case "isEmpty": conditions += ` ${prefix} ${column} = ''`; break; default: throw new Error(`Unsupported condition: ${condition}`); } }); const mainQuery = `SELECT * FROM public.sample_data_orders ${conditions}`; return { mainQuery }; } return createSQLQueries(filterData);

这段脚本的核心逻辑值得拆解:

  • 遍历过滤器:components.table1.filters是一个数组,每个元素包含condition(过滤条件类型)、value(过滤值)、column(目标列名)三个字段;
  • 条件拼接:第一个条件以WHERE开头,后续条件以AND连接;
  • 条件类型映射:脚本通过switch将过滤器的条件类型翻译为对应的 SQL 片段,各类型含义如下:
condition 取值含义生成的 SQL
contains包含column ILIKE '%value%'
doesNotContains不包含column NOT ILIKE '%value%'
matches/equals等于column = 'value'
ne不等于column != 'value'
nl为空(NULL)column IS NULL
isEmpty为空字符串column = ''

注意:示例脚本采用字符串插值方式拼接过滤值,仅适用于演示与受信任的数据场景。若过滤值可能来自不可信输入,建议在生产环境对列名与值做必要的转义或校验,避免 SQL 注入风险。

第三步:为 RunJS 查询添加事件处理器

RunJS 查询执行成功后,需要触发数据查询重新取数。为 RunJS 查询添加如下事件处理器:

  • Event(事件):Query Success
  • Action(动作):Run Query
  • Query(查询):选择你的数据查询(即第一步创建的 Postgres 查询)

第四步:让数据查询使用动态 SQL

编辑你的数据查询,将 SQL 替换为引用 RunJS 查询输出结果的模板字符串:

{{queries.runjs1.data.mainQuery}}

这里queries.runjs1.data.mainQuery即 RunJS 脚本返回对象中的mainQuery字段。ToolJet 的查询模板语法会在执行前将其解析为最终的 SQL 语句,从而把过滤条件"注入"到数据库查询中。

第五步:将 Table 的过滤变化接入查询链路

现在把 Table 组件的过滤行为与 RunJS 查询连接起来。为 Table 组件添加事件处理器:

  • Event(事件):Filter Changed
  • Action(动作):Run Query
  • Query(查询):选择你的 RunJS 查询

配置完成后,每次过滤器发生变化,都会依次触发:Table 的Filter Changed事件 → 运行 RunJS 查询(重新拼接 SQL)→ RunJS 的Query Success事件 → 运行数据查询(按新条件取数)→ Table 的 Data 属性刷新。这条事件链正是服务端过滤的完整闭环。

从源码看,Filter Changed事件在 widgets/table.js 中被定义为 Table 组件的标准事件(onFilterChanged),同时组件暴露了filters这一可访问变量(见 widgets/table.js),开发者也可以通过组件方法setFilters/clearFilters(见 widgets/table.js)以编程方式设置或清空过滤器,灵活驱动服务端过滤逻辑。

第六步:添加加载状态(Loading State)

为了避免过滤执行期间界面无反馈,可以给 Table 组件加上加载状态:

  1. 在 Table 组件属性面板中找到Additional Actions(附加操作)区域;
  2. 点击Loading State右侧的fx图标,进入表达式编辑模式;
  3. 输入{{queries.getOrders.isLoading}}(将getOrders替换为你实际的查询名称)。

这样当数据查询正在执行时,Table 组件会展示加载状态,过滤交互的反馈更清晰。

实现原理小结

从源码层面回看整个实现,服务端过滤的机制可以归纳为三点:

  1. 模式切换:serverSideFilter属性(clientServerSwitch类型)决定过滤是否由前端接管。开启后,useTable.js 将 TanStack Table 置于manualFiltering模式,前端不再执行本地过滤;
  2. 状态暴露:过滤器的当前状态通过components.table1.filters暴露给应用,包含condition、value、column字段,供 RunJS 读取并翻译为 SQL;
  3. 事件驱动:过滤条件变化触发Filter Changed事件(widgets/table.js),配合 RunJS 的Query Success事件形成"过滤 → 拼 SQL → 重新取数"的完整链路。

最终的效果是:当用户在 Table 组件上应用一个或多个过滤器时,查询在服务器端执行,过滤作用于数据集的全部记录,而非仅限前端已加载的数据——这正是大规模数据集场景下保持查询准确性与性能的关键所在。同理,搜索(Search)、排序(Sort)、分页(Pagination) 等服务端操作也可参照本文的事件链模式进行编排。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询