ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ng-zorro-antd 表格行选择与批量操作实战:基于 `nzChecked` 的联动选择与数据状态自管理

ng-zorro-antd 表格行选择与批量操作实战:基于 `nzChecked` 的联动选择与数据状态自管理 UI组件前端【免费下载链接】ng-zorro-antdAngular UI Component Library based on Ant Design项目地址https://gitcode.com/gh_mirrors/ng/ng-zorro-antd点击查看免费下载导读在数据密集型后台界面中“勾选多行 → 批量操作 → 清空选择”是最常见不过的交互闭环。ng-zorro-antd 的nz-table通过将第一列声明为联动选择列即可获得与nz-checkbox完全一致的表头全选/半选、行单选能力。本篇以仓库中的官方示例 row-selection-and-operation.ts 为骨架完整讲解从列声明、全选/半选状态推导、分页联动到发起操作并清空选择的完整实现并结合 th-selection.component.ts、td-addon.component.ts 等源码揭示其底层原理。读完你将能独立实现一个带批量操作、支持禁用行、分页联动与加载态的表格选择方案。一、功能定位第一列即选择列ng-zorro-antd 表格的“行选择与操作”方案非常轻量——不需要额外的选择状态组件只要在模板里把第一列声明为带[nzChecked]等属性的th/td即可。表头th增加[nzChecked]后获得与nz-checkbox一样的功能全选 / 取消全选并配合[nzIndeterminate]呈现半选状态表体每一行的td同样通过[nzChecked]声明行内复选框选择完毕后触发批量操作操作完成后清空选择集合数据逻辑选中集合的增删、全选判断、半选判断需要开发者自行控制——这也是该方案的核心约定nz-table只提供 UI 联动与事件回调不替你维护选中状态。官方对该功能的描述与此完全一致见 row-selection-and-operation.md第一列是联动的选择框增加[nzChecked]后th获得和nz-checkbox一样的功能选择后进行操作完成后清空选择数据逻辑需要自行控制。二、完整实现示例选择 操作 清空官方演示组件NzDemoTableRowSelectionAndOperationComponent是这一交互的标准模板源码见 row-selection-and-operation.ts。以下为完整可运行实现import { Component, OnInit, signal } from angular/core; import { NzButtonModule } from ng-zorro-antd/button; import { NzTableModule } from ng-zorro-antd/table; export interface Data { id: number; name: string; age: number; address: string; disabled: boolean; } Component({ selector: nz-demo-table-row-selection-and-operation, imports: [NzButtonModule, NzTableModule], template: div classsend-request button nz-button nzTypeprimary [disabled]setOfCheckedId().size 0 [nzLoading]loading() (click)sendRequest() Send Request /button spanSelected {{ setOfCheckedId().size }} items/span /div nz-table #rowSelectionTable nzShowPagination nzShowSizeChanger [nzData]listOfData() (nzCurrentPageDataChange)onCurrentPageDataChange($event) thead tr th [nzChecked]checked() [nzIndeterminate]indeterminate() nzLabelSelect all (nzCheckedChange)onAllChecked($event) /th thName/th thAge/th thAddress/th /tr /thead tbody for (data of rowSelectionTable.data; track data.id) { tr td [nzChecked]setOfCheckedId().has(data.id) [nzDisabled]data.disabled [nzLabel]data.name (nzCheckedChange)onItemChecked(data.id, $event) /td td{{ data.name }}/td td{{ data.age }}/td td{{ data.address }}/td /tr } /tbody /nz-table , styles: .send-request { margin-bottom: 16px; } .send-request span { margin-inline-start: 8px; } }) export class NzDemoTableRowSelectionAndOperationComponent implements OnInit { readonly checked signal(false); readonly loading signal(false); readonly indeterminate signal(false); readonly listOfData signalreadonly Data[]([]); readonly listOfCurrentPageData signalreadonly Data[]([]); readonly setOfCheckedId signal(new Setnumber()); updateCheckedSet(id: number, checked: boolean): void { this.setOfCheckedId.update(setOfCheckedId { const next new Set(setOfCheckedId); if (checked) { next.add(id); } else { next.delete(id); } return next; }); } onCurrentPageDataChange(listOfCurrentPageData: readonly Data[]): void { this.listOfCurrentPageData.set(listOfCurrentPageData); this.refreshCheckedStatus(); } refreshCheckedStatus(): void { const listOfEnabledData this.listOfCurrentPageData().filter(({ disabled }) !disabled); const checked listOfEnabledData.every(({ id }) this.setOfCheckedId().has(id)); this.checked.set(checked); this.indeterminate.set(listOfEnabledData.some(({ id }) this.setOfCheckedId().has(id)) !checked); } onItemChecked(id: number, checked: boolean): void { this.updateCheckedSet(id, checked); this.refreshCheckedStatus(); } onAllChecked(checked: boolean): void { this.listOfCurrentPageData() .filter(({ disabled }) !disabled) .forEach(({ id }) this.updateCheckedSet(id, checked)); this.refreshCheckedStatus(); } sendRequest(): void { this.loading.set(true); const requestData this.listOfData().filter(data this.setOfCheckedId().has(data.id)); console.log(requestData); setTimeout(() { this.setOfCheckedId.set(new Setnumber()); this.refreshCheckedStatus(); this.loading.set(false); }, 1000); } ngOnInit(): void { this.listOfData.set( new Array(100).fill(0).map((_, index) ({ id: index, name: Edward King ${index}, age: 32, address: London, Park Lane no. ${index}, disabled: index % 2 0 })) ); } }该示例使用 Angular 最新的signal状态管理与for控制流语法并只依赖NzButtonModule与NzTableModule两个模块适合作为功能的最小可运行起点。三、数据状态自管理五段逻辑拆解正如文档强调的“数据逻辑需要自行控制”示例中所有选中状态都由组件内部状态驱动。可拆解为五个关键部分1. 选中集合Setnumber作为唯一数据源setOfCheckedId是一个signal(new Setnumber())只存选中行的id。之所以选用Set而非boolean[]是因为它天然支持跨页聚合选中的行可能分布在多页且查询has(id)是 O(1) 操作。updateCheckedSet采用不可变更新复制出一个新Set再增删避免直接修改原对象保证signal变更可被侦测。2. 当前页数据缓存listOfCurrentPageData通过表格的(nzCurrentPageDataChange)事件把“当前页面展示的数据”缓存到listOfCurrentPageData。这是全选/半选判断的数据基础——分页场景下表头“全选”语义是“选中当前页所有未禁用行”而非全部 100 条数据。从源码可见该事件由 table.component.ts 在数据变化时触发Output() readonly nzCurrentPageDataChange new EventEmitterreadonly T[]()nzShowPagination默认true与nzShowSizeChanger默认false可在全局配置中开启共同决定分页展示行为。3. 状态刷新refreshCheckedStatus推导全选与半选const listOfEnabledData this.listOfCurrentPageData().filter(({ disabled }) !disabled); const checked listOfEnabledData.every(({ id }) this.setOfCheckedId().has(id)); this.checked.set(checked); this.indeterminate.set(listOfEnabledData.some(({ id }) this.setOfCheckedId().has(id)) !checked);全选条件当前页所有未禁用行都在选中集合中半选条件至少有一个未禁用行被选中但并非全部选中。先过滤disabled行保证禁用行既不会被every卡住也不会触发半选误判。4. 行级切换onItemChecked勾选/取消某一行时更新Set后立即刷新表头状态。表头状态是从选中集合推导出来的派生值而非独立维护的布尔量这就是“联动”的本质——任何行变化都会自动反映到表头反之表头操作也会批量写入集合。5. 全选onAllCheckedthis.listOfCurrentPageData() .filter(({ disabled }) !disabled) .forEach(({ id }) this.updateCheckedSet(id, checked));表头勾选事件携带的checked布尔值被应用到当前页所有未禁用行的id上然后同样刷新状态。注意此处是在事件回调中逐条updateCheckedSet虽然多次触发signal.update但语义清晰、逻辑一致。四、操作与清空sendRequest 的完整闭环批量操作通过sendRequest()实现流程如下禁用与加载态按钮的[disabled]setOfCheckedId().size 0保证无选中时不可点击[nzLoading]loading()在请求期间展示加载转圈收集选中数据this.listOfData().filter(data this.setOfCheckedId().has(data.id))从全量数据而非当前页中提取被选中的行因为选中集合可能跨页模拟请求示例用setTimeout模拟 1 秒异步请求console.log(requestData)输出待提交的数据实际项目中此处替换为 HTTP 调用清空选择请求结束后this.setOfCheckedId.set(new Setnumber())重置选中集合再调用refreshCheckedStatus()让表头全选框、半选框同步复位最后loading置回false。这段“收集 → 请求 → 清空 → 复位”的流程正是文档所说“选择后进行操作完成后清空选择”的标准落地方式。五、源码级原理th与td的选择能力从何而来“给th/td加[nzChecked]就能得到 checkbox”这一魔法本质是属性选择器组件。ng-zorro-antd 用两个独立组件分别接管了表头与单元格1. 表头选择组件NzThSelectionComponent定义在 th-selection.component.ts选择器为th[nzSelections], th[nzChecked], th[nzShowCheckbox], th[nzShowRowSelection]只要th上出现任一属性该组件即生效。它内部渲染nz-table-selection并对外暴露输入/输出类型说明[nzChecked]boolean全选框是否选中默认false[nzIndeterminate]boolean全选框半选状态默认false[nzDisabled]boolean全选框禁用默认false[nzLabel]string \| null全选框的aria-label无障碍标签默认null[nzSelections]Array{ text, onSelect }表头下拉菜单选项及回调默认[][nzShowCheckbox]boolean是否显示 checkbox默认false[nzShowRowSelection]boolean是否显示下拉选择菜单默认false(nzCheckedChange)EventEmitterboolean选中状态变化回调源码中值得注意的两处自动行为ngOnChanges首次传入nzSelections且未显式设置过nzShowExpand时自动开启nzShowRowSelection首次传入nzChecked且未显式设置过nzShowCheckbox时自动开启nzShowCheckbox。也就是说只要写[nzChecked]...复选框就会被渲染出来无需额外声明nzShowCheckbox这正是“增加[nzChecked]后th获得 checkbox 功能”的机制来源。onCheckedChange回调会把内部状态同步回nzChecked并向上emit。2. 单元格选择组件NzTdAddOnComponent定义在 td-addon.component.ts选择器td[nzChecked], td[nzDisabled], td[nzIndeterminate], td[nzIndentSize], td[nzExpand], td[nzShowExpand], td[nzShowCheckbox]当td带nzChecked等属性时组件渲染一个nz-checkbox复选框并同时处理展开图标与缩进nzExpand/nzIndentSize因此选择列与展开列可以共存于同一单元格。其对外 API 与th版基本对称nzChecked、nzDisabled、nzIndeterminate、nzLabel、nzCheckedChange且同样有“首次传入nzChecked即自动开启nzShowCheckbox”的默认行为。3. 内部选择组件NzTableSelectionComponent定义在 selection.component.ts负责真正渲染复选框与“下拉全选菜单”nzSelections配置的text/onSelect选项可注入如“全部选中”“全部取消”“奇数行”等批量动作。复选框通过[ngModel]checked与(ngModelChange)实现受控半选态映射到nz-checkbox的[nzIndeterminate]。4. 表格容器侧配合nz-table 提供nzData数据输入、nzShowPagination默认true、nzShowSizeChanger默认false等分页开关并通过nzCurrentPageDataChange通知当前页数据变化#rowSelectionTable模板引用变量上的.data属性则是当前页渲染数据的直接来源演示模板即用rowSelectionTable.data驱动for渲染。测试用例 td.spec.ts 验证了ant-table-selection-column样式类与半选态ant-checkbox-indeterminate的实际生效可作为底层行为的佐证。六、API 速查与进阶指引完整的th/td选择相关 API 说明可见官方文档 index.zh-CN.md关键参数如下表格级[nzData]数据源、[nzShowPagination]是否显示分页默认true、[nzShowSizeChanger]是否可改每页条数默认false可经全局配置开启、(nzCurrentPageDataChange)当前页数据变化回调表头th级[nzShowCheckbox]是否添加 checkbox、[nzChecked]是否选中可双向绑定、(nzCheckedChange)选中回调、[nzSelections]下拉选择项Array{ text, onSelect }、[nzIndeterminate]半选态单元格td级[nzShowCheckbox]、[nzChecked]、(nzCheckedChange)另支持[nzDisabled]禁用单行复选框。更多进阶形态可参考同目录下的 row-selection-custom.ts自定义全选下拉菜单以及table组件的expand、edit等系列 demo见 components/table/demo便于将选择能力与展开行、行编辑组合使用。七、小结与三个易错点回顾整个实现“自行控制数据逻辑”是贯穿始终的设计前提落地时需特别注意三点全选只对当前页生效表头全选基于listOfCurrentPageData计算跨页选中必须依赖Set的持久性——翻页后再回到原页行仍保持选中禁用行不参与全选/半选判断refreshCheckedStatus与onAllChecked都先filter(({ disabled }) !disabled)否则禁用行会破坏every/some的语义操作完成后务必清空并复位setOfCheckedId.set(new Set())之后还需调用refreshCheckedStatus()否则表头全选框会残留勾选状态破坏下一次选择的体验。赞分享UI组件前端【免费下载链接】ng-zorro-antdAngular UI Component Library based on Ant Design项目地址https://gitcode.com/gh_mirrors/ng/ng-zorro-antd点击查看免费下载相关推荐终极指南Lightbug HTTP的Cookie管理与会话控制终极指南Lightbug HTTP的Cookie管理与会话控制 Lightbug HTTP是一个简单快速的Mojo HTTP框架为开发者提供了高效的CookUI组件前端设计系统ng-zorro-antd TreeView 带选择框的树checkbox 级联勾选完整实战指南ng zorro antd TreeView 带选择框的树checkbox 级联勾选完整实战指南 带选择框的树Tree with checkboxes是数UI组件前端ng-zorro-antd 表单联动实战基于 setValue 与 valueChanges 的控件动态赋值ng zorro antd 表单联动实战基于 setValue 与 valueChanges 的控件动态赋值 导读 本文以 ng zorro antdAngUI组件前端上一篇SpinningMomo为《无限暖暖》摄影玩家量身打造的终极窗口调整工具下一篇OBS Studio浏览器源调试实战技巧从卡顿到流畅的性能优化指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表