Angular 5 DataTable:点击按钮刷新列与数据问题
解决Angular DataTable封装组件中列更新不生效的问题
这个问题我之前也碰到过——angular-data-tables默认不会自动监听列配置的变化,你的通用组件大概率只在初始化阶段读取了一次columns输入属性,后续父组件修改后没有触发表格的重新渲染。下面给你一套可行的解决方案:
1. 监听columns输入属性的变化
首先得让你的通用DataTable组件感知到columns的变更,推荐用setter语法或者ngOnChanges钩子来实现:
方案A:使用@Input() setter
private _columns: any[] = []; // 通过setter监听列配置变化 @Input() set columns(value: any[]) { this._columns = [...value]; // 用扩展运算符创建新数组,确保不可变性 // 列变化时触发表格刷新 this.refreshTable(); } get columns(): any[] { return this._columns; }
方案B:使用ngOnChanges钩子
import { SimpleChanges, OnChanges } from '@angular/core'; // 组件实现OnChanges接口 export class DataTableComponent implements OnChanges { @Input() columns: any[] = []; ngOnChanges(changes: SimpleChanges) { // 只在columns首次初始化以外的变化时触发刷新 if (changes['columns'] && !changes['columns'].firstChange) { this.refreshTable(); } } }
2. 实现表格刷新逻辑
angular-data-tables需要手动销毁旧表格再重新初始化,才能识别新的列配置。假设你的组件里有这些变量:
import { DataTableDirective } from 'angular-datatables'; import { Subject } from 'rxjs'; @ViewChild(DataTableDirective, { static: false }) dtElement: DataTableDirective; dtOptions: DataTables.Settings = {}; dtTrigger: Subject<any> = new Subject(); dtInstance: Promise<DataTables.Api>;
然后写refreshTable方法:
refreshTable() { // 先销毁已初始化的表格 this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => { dtInstance.destroy(); // 根据新的columns重新生成dtOptions this.initDtOptions(); // 触发表格重新渲染 this.dtTrigger.next(); }); } // 初始化表格配置的方法,把columns映射为datatables需要的列格式 initDtOptions() { this.dtOptions = { columns: this._columns.map(col => ({ title: col.name, // 列名 data: col.field, // 绑定的数据源字段 orderable: col.orderable ?? true, // 可选:是否允许排序 searchable: col.searchable ?? true // 可选:是否允许搜索 })), // 其他表格配置(比如分页、排序规则等) }; }
别忘在组件销毁时清理dtTrigger:
ngOnDestroy() { this.dtTrigger.unsubscribe(); }
3. 模板配合调整
确保你的模板里正确引用了dtOptions和dtTrigger:
<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="row-border hover" ></table>
4. 父组件修改columns的注意事项
如果你的通用组件用了OnPush变更检测策略,必须保证每次修改columns时都返回新数组,不能直接修改原数组的元素:
// 父组件中修改列名的正确方式 this.columns = this.columns.map(col => col.field === 'username' ? { ...col, name: '用户名' } : col ); // 父组件中新增列的正确方式 this.columns = [...this.columns, { field: 'email', name: '邮箱' }];
这样Angular才能检测到输入属性的变化,触发组件的更新。
补充:同步更新表格数据
如果修改列的同时需要刷新数据,记得在refreshTable之前调用数据加载方法,比如在setter里:
@Input() set columns(value: any[]) { this._columns = [...value]; this.loadTableData(); // 重新获取数据 this.refreshTable(); }
内容的提问来源于stack exchange,提问作者Feroz Siddiqui
相关产品推荐
相关产品推荐

