资讯动态

ToolJet Kanban 组件详解:看板数据结构、事件机制与组件专属操作(CSA)实战指南

发布时间:2026/9/10 7:36:34 来源:尧图企业网站定制
ToolJet Kanban 组件详解看板数据结构、事件机制与组件专属操作CSA实战指南【免费下载链接】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 官方组件文档与前端源码系统讲解 Kanban看板组件的完整用法如何用columnData/cardData绑定动态数据、卡片内cardData模板变量、6 类事件与 7 个暴露变量、4 个可脚本调用的组件专属操作CSA以及卡片详情弹窗、删除区、样式与设备适配等全部配置项。读完后你可以把一个静态任务板改造成由查询驱动、事件可监听、卡片可增删移改的完整工作流看板并理解其底层基于dnd-kit的拖拽实现原理。一、组件定位与默认结构Kanban组件用于以可视化看板方式组织与排期任务提供透明的任务流转工作流可配置显示列数、启用/禁用“Add Card”按钮并把外部数据绑定到卡片上参见 官方文档。在 组件配置文件 中可以看到新添加的 Kanban 组件默认宽度 40、高度 490并自带两个默认的Text子组件直接绑定到当前卡片数据上// 默认子组件 1卡片标题top: 20, left: 4, 加粗 16px text: {{cardData.title}} // 默认子组件 2卡片描述top: 50, left: 4, 14px text: {{cardData.description}}默认看板数据为 3 列r1To Do /r2In Progress /r3Done与 10 张卡片卡片默认宽度302、高度100删除区默认文案Drop here to delete——即开箱即可运行一个完整的“待办-进行中-完成”看板。卡片与弹窗内的受限组件:::info 受限组件 Kanban 的Card与Popout卡片详情弹窗中不允许放置部分组件CardCalendar、Kanban、Form、Tabs、Modal、ListView、ContainerPopoutCalendar、Kanban :::这一限制从源码结构看可以避免嵌套拖拽容器DndContext与嵌套弹窗造成状态冲突。二、数据绑定Column data 与 Card data这是看板数据模型的骨架两项均为code类型属性支持直接写数组字面量或绑定查询结果属性说明期望值Column data以对象数组或返回对象数组的查询提供列的id与title{{[{ id: c1, title: to do },{ id: c2, title: in progress },{ id: c3, title: Completed }]}}或{{queries.xyz.data}}Card data以对象数组或查询提供卡片的id、title、columnId可含description等自定义字段{{[{ id: r1, title: Title 1, description: Description 1, columnId: c1 },{ id: r2, title: Title 2, description: Description 2, columnId: c2 },{ id: r3, title: Title 3, description: Description 3, columnId: c3 }]}}或{{queries.abc.data}}两条强制约束缺失时看板无法正确渲染column data中每列必须提供idid可为string或numberCard data中每张卡片必须提供id和columnId两者类型同为string或number。从 helpers/utils.js 的实现可以印证这一点convertArrayToObj直接以d.id作为键构建containers[d.id] dgetColumnData只做columnData.map(container container.id)getCardData则以card.columnId分组、card.id入列。因此id缺失或重复都会破坏“列→卡片 ID 列表”的映射结构。非数组输入会被normalizeCardData归一为[]表现为空看板而不是报错。三、在卡片内使用cardData变量卡片内部组件需要动态展示当前卡片的数据时使用cardData键。例如把卡片上一个 Text 组件的Data属性设为{{cardData.title}} // 将 title 替换为你数据中的字段名如 cardData.description底层机制在 KanbanBoard.jsx 中实现组件通过updateCardDataInCustomResolvables(id, flatCardData.map(d ({ cardData: d })), cardData, moduleId)为每张卡片注册一条独立的cardData可解析值。也就是说同一张卡片内的所有子组件共享“这张卡片”这一上下文的cardData而不同卡片各自的cardData互不干扰。因此除了内置的title/description默认占位你的查询数据中的任意字段如assignee、dueDate都可以在卡片内以{{cardData.字段名}}直接引用。四、板面配置Card width / Card height / 添加与删除区属性说明期望值Card width设置卡片宽度数值默认{{302}}Card height设置卡片高度数值默认{{100}}Enable add card显示/隐藏看板上的Add Cards按钮默认启用点击属性旁的fx可绑定{{true}}/{{false}}动态控制Show delete button显示/隐藏看板底部的Drop here to delete cards删除区默认启用同样可通过fx动态控制几个源码级细节列容器宽度由cardWidth推导KanbanBoard.jsx 中width: \${(Number(cardWidth) || 300) 48}px即卡片宽度加 48px 内边距删除区在代码中是id为常量voidTRASH_ID的Trash组件拖拽卡片悬停其上并松开即触发删除 Add Card按钮点击时触发onAddCardClick事件且受enableAddCard控制禁用时按钮被设为invisible类配置中还存在Delete zone label属性默认文案Drop here to delete可自定义删除区提示文字。五、卡片详情弹窗Popout配置文档的 Events 一节提到“点击卡片打开弹窗”其对应配置在 kanban.js 的Card details modal小节属性说明默认值Open modal on card click点击卡片是否打开详情弹窗{{true}}Modal size弹窗尺寸可选small/medium/large/fullscreenlgmediumHeight弹窗高度400弹窗内的 Popout 区域可像 Card 一样放置组件受前文所列受限组件约束组件内同样可读取cardData。六、Events6 个事件的触发时机在右侧属性面板的Events区点击Add handler即可为下列事件添加处理器与 ToolJet 其他组件一样支持同一事件绑定多个 handler事件触发时机On update卡片数据id、title、description 或 columnID通过组件专属操作CSA被更新时触发On add card click点击看板上的Add card按钮时触发Card removed卡片被删除时触发拖入底部删除区或通过 CSA 删除Card added通过 CSA 向看板添加卡片时触发Card moved卡片在看板上的位置改变时触发拖拽或通过 CSA 移动Card selected点击卡片打开弹窗选中时触发与事件对应的内部实现每个 CSA 或拖拽落点在执行完状态变更后调用fireEvent(onCardAdded | onCardRemoved | onCardMoved | onUpdate)见 KanbanBoard.jsx。需要注意一个细节删除卡片若通过拖入删除区overId TRASH_ID分支只会设置lastRemovedCard并触发onCardRemoved而通过 CSAdeleteCard删除时同理。事件更多说明可参考 ToolJet 文档站中的Action Reference分类。七、Exposed Variables7 个暴露变量全解变量说明访问方式updatedCardData看板中所有卡片的最新值集合。只有当对任意卡片执行过移动、添加、删除或更新操作后才有值直接读取{{components.kanban1.updatedCardData}}lastAddedCard最后添加的卡片含id、title、description、columnId{{components.kanban1.lastAddedCard.title}}lastRemovedCard最近被删除的卡片含id、title、description、columnId{{components.kanbanboard1.lastRemovedCard.title}}lastCardMovement最近移动的卡片originColumnId、destinationColumnId、originCardIndex、destinationCardIndex以及cardDetails对象含id、title、description、columnId{{components.kanbanboard1.lastCardMovement.cardDetails.title}}或{{components.kanbanboard1.lastCardMovement.destinationCardIndex}}lastSelectedCard最后选中点击查看卡片的id、title、columnId、description{{components.kanban1.lastSelectedCard.columnId}}lastUpdatedCard最后通过 CSA 更新的卡片含id、title、description、columnId{{components.kanban1.lastUpdatedCard.columnId}}lastCardUpdate记录本次 CSA 更新中“被修改属性”的旧值与新值数组{{components.kanban1.lastCardUpdate[0].title.oldValue}}这 7 个变量与 kanban.js 中exposedVariables的声明一一对应。lastCardUpdate的“新旧值对比”结构由deep-object-diff计算得出——updateCardData实现中先对更新前后的卡片做diff再把变更键映射为{ [key]: { oldValue, newValue } }数组这解释了为什么访问写法是lastCardUpdate[0].title.oldValue数组下标 属性名 oldValue/newValue。lastCardMovement在拖拽与 CSA 两条路径下都会被写入拖拽路径记录originCardIndex/destinationCardIndex数组内索引CSAmoveCard路径则把卡片插入目标列首位、destinationIndex为0。八、Component Specific ActionsCSA脚本化操作看板以下 4 个操作可在任意事件 handler 的RunJS查询中调用实现对看板的编程式控制参数签名以 kanban.js 中actions定义为准操作说明调用示例updateCardData更新卡片数据components.kanban1.updateCardData(c1, { title: New Title })moveCard把卡片移动到另一列await components.kanban1.moveCard(c1, r2)第一个参数为卡片 id第二个为目标列 idaddCard向看板添加卡片await components.kanban1.addCard(c1, { title: New Title })deleteCard删除卡片await components.kanban1.deleteCard(c2)参数为卡片 idCSA 的防御性校验在 KanbanBoard.jsx 中可见updateCardData/moveCard/deleteCard目标卡片不存在时弹出Card not found提示并中止moveCard若卡片已处于目标列columnId相同则直接返回不触发事件addCard卡片 id 已存在时提示Card already existscolumnId缺失或指向不存在的列时提示Column Id not found。每个 CSA 成功后都会同步刷新updatedCardData及对应的lastXxx变量并触发对应事件因此“CSA 改状态 → 暴露变量更新 → 事件 handler 执行后续查询/保存”构成了完整的可编程闭环。一个典型的“点击按钮落库”场景// 事件 handler 中的 RunJS 示例 // 1. 把最近选中的卡片移动到其他列 await components.kanban1.moveCard(components.kanban1.lastSelectedCard.id, r3); // 2. 更新卡片标题 components.kanban1.updateCardData(components.kanban1.lastSelectedCard.id, { title: Done! }); // 3. 把最新全量卡片数据提交到后端查询 await queries.saveCards.run({ cards: components.kanban1.updatedCardData });九、拖拽实现原理基于 dnd-kit 的多列排序从源码结构看看板拖拽由dnd-kit驱动KanbanBoard.jsxDndContext注册了MouseSensor、TouchSensor与KeyboardSensor键盘坐标由 multipleContainersKeyboardCoordinates.js 的coordinateGetter提供支持跨列键盘移动碰撞检测使用rectIntersection每个列是一个tj-kanban-container-{columnId}可放置容器列内是SortableContextverticalListSortingStrategy的垂直排序上下文onDragOver负责跨列实时重排并记录lastCardMovement中间态onDragEnd处理落点落点在删除区void走删除分支落点位置变化走arrayMove重排分支并在此统一写入lastCardMovement、触发onCardMoved拖拽中的卡片由DragOverlay渲染松手时有半透明落位动画dropAnimationopacity: 0.5。这也解释了文档约束的由来findContainer通过tj-kanban-container-前缀识别列容器跨列拖拽判定、卡片归属都依赖这套 ID 约定因此列/卡片的id必须是字符串或数字且保持稳定。十、General、Devices 与 Styles 配置TooltipGeneral 折叠区在General区设置字符串后鼠标悬停组件即显示该文案作为提示。当前实现还支持Tooltip format切换plainText/markdown/html默认plainText可让提示文本支持 Markdown 或 HTML 渲染。Devices属性说明Show on desktop桌面视图下是否可见。默认{{true}}可用开关设置或点击fx填入逻辑表达式动态控制Show on mobile移动视图下是否可见。默认{{false}}同样支持 fx 动态绑定Styles样式说明Disable禁用后组件被锁定且不可交互。默认值{{false}}文档表格中“默认禁用”的表述与源码默认值{{false}}不一致以源码definition.styles.disabledState为准即默认未禁用Visibility控制组件可见性{{false}}时应用部署后组件不显示。默认{{true}}Accent color列标题底色/强调色可输入 Hex 值或用取色器选择默认值为 CSS 变量var(--cc-primary-brand) Add Card按钮与列标题共用该色源码中colAccentColor { color: #fff, backgroundColor: accentColor ?? #4d72fa }从 Kanban.jsx 可见disabledState会通过data-disabled属性与useDisableInert钩子将看板标记为inert使其按钮与内嵌组件同时退出 Tab 键盘焦点顺序visibility为false时外层容器直接display: none。十一、兼容旧版 KanbanBoard 组件仓库中另有一份 kanbanBoard.js 配置文件首行注释明确写道KanbanBoard 组件已弃用deprecated该配置仅为兼容存量应用中的旧组件而保留。旧版属性名为columns事件多一个onCardUpdated新版并入onUpdate且暴露变量中没有lastSelectedCard/lastCardUpdate。如果你在新建应用中看到 Kanban Board 选项应优先使用新版Kanban组件旧应用数据可沿用旧组件继续工作但不再获得新特性。十二、小结数据模型列只需idtitle卡片必须带idcolumnId两者均支持字面量数组或{{queries.xxx.data}}查询绑定卡片内组件统一通过{{cardData.字段}}读取当前卡片数据。交互能力6 个事件覆盖更新、加卡点击、删除、添加、移动、选中7 个暴露变量updatedCardData及 6 个lastXxx让 handler 能精确感知每次操作前后的状态。编程控制addCard/deleteCard/moveCard/updateCardData四个 CSA 可在 RunJS 中 await 调用与事件、暴露变量组合即可实现“拖拽→事件→落库”的完整闭环。底层实现基于dnd-kit的DndContext 多容器SortableContext支持鼠标、触摸与键盘三套 sensor删除区是一个 id 为void的特殊放置目标。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价