AngularJS DataTables(i-lin) Ajax请求后渲染完整表格问题求助
解决AngularJS DataTables先显示静态列再加载动态列的用户体验问题
你遇到的核心问题是表格初始化时只有静态列,后续通过异步请求获取动态列后再更新,导致表格重新渲染,让用户看到两次界面变化。下面是几个针对性的解决方法,帮你优化用户体验:
思路一:先获取动态列数据,再初始化DataTables
这是最直接的方案——先拿到所有需要的列信息(静态+动态),再构建完整的dtColumns和dtOptions,最后让表格一次性渲染完成,用户不会看到任何中间状态。
修改代码如下:
// 先调用接口获取payment_methods,拿到列信息后再初始化表格 Module.fetchSalesData({ startdate: $filter('date')($scope.item.startdate, 'yyyy-MM-dd'), enddate : $filter('date')($scope.item.enddate, 'yyyy-MM-dd'), // 如果接口支持,可以传length:0只拿列信息,减少数据传输量 length: 0 }).then(function(res) { $scope.payment_methods = res.data; // 构建完整的列集合:静态列 + 动态列 $scope.dtColumns = [ DTColumnBuilder.newColumn('invoice_date') .withTitle('Date') .withOption('sWidth', '10%'), DTColumnBuilder.newColumn('ref_num').withTitle('Description') ]; // 追加动态列 angular.forEach($scope.payment_methods, function (value) { $scope.dtColumns.push( DTColumnBuilder.newColumn(value).withTitle(value) .notSortable().withClass('text-right') .withOption('stateSave', true) .renderWith(function (data, type, full) { data = typeof data === 'undefined' ? '0.00' : data; return $filter('currency')(data, ''); }) ); }); // 现在初始化DataTables的配置项 $scope.dtOptions = DTOptionsBuilder .newOptions() .withOption('ajax', function (data, callback, settings) { settings.sAjaxDataProp = 'trans'; Module.fetchSalesData({ draw: data.draw, length: data.length, start: data.start, search : data.search.value, count_again : $scope.countAgain, startdate: $filter('date')($scope.item.startdate, 'yyyy-MM-dd'), enddate : $filter('date')($scope.item.enddate, 'yyyy-MM-dd'), payee_id: $scope.item.payee_id, staff_id: $scope.item.staff_id, order: data.order }).then(function(res) { callback(res); $scope.countAgain = false; }) }) .withOption('serverSide', true); });
思路二:用Angular指令控制表格的显示时机
通过ng-if或ng-show隐藏表格,直到所有列都准备完毕后再显示。这样用户只会看到最终的完整表格,完全不会感知到静态列的中间状态。
修改HTML:
<!-- 只有当dtColumns包含动态列时,才渲染表格 --> <table id="saleReport" class="report-table table-striped table table-bordered table-condensed table-hover data-table" datatable="" dt-options="dtOptions" dt-columns="dtColumns" dt-instance="dtInstance" ng-if="dtColumns && dtColumns.length > 2">
修改AngularJS代码(去掉不可靠的setTimeout):
$scope.dtOptions = DTOptionsBuilder .newOptions() .withOption('ajax', function (data, callback, settings) { settings.sAjaxDataProp = 'trans'; Module.fetchSalesData({ draw: data.draw, length: data.length, start: data.start, search : data.search.value, count_again : $scope.countAgain, startdate: $filter('date')($scope.item.startdate, 'yyyy-MM-dd'), enddate : $filter('date')($scope.item.enddate, 'yyyy-MM-dd'), payee_id: $scope.item.payee_id, staff_id: $scope.item.staff_id, order: data.order }).then(function(res) { $scope.payment_methods = res.data; // 直接追加动态列,Angular会自动触发digest更新视图 angular.forEach($scope.payment_methods, function (value) { $scope.dtColumns.push( DTColumnBuilder.newColumn(value).withTitle(value) .notSortable().withClass('text-right') .withOption('stateSave', true) .renderWith(function (data, type, full) { data = typeof data === 'undefined' ? '0.00' : data; return $filter('currency')(data, ''); }) ); }); callback(res); $scope.countAgain = false; }) }) .withOption('serverSide', true); // 初始化静态列 $scope.dtColumns = [ DTColumnBuilder.newColumn('invoice_date') .withTitle('Date') .withOption('sWidth', '10%'), DTColumnBuilder.newColumn('ref_num').withTitle('Description') ];
思路三:正确销毁并重新初始化表格
如果之前销毁表格失败,大概率是操作时机不对或没有在Angular上下文里处理。可以利用dtInstance管理表格实例,拿到动态列后先销毁旧表格,再更新列并重新渲染。
修改代码:
// 初始化dtInstance用于管理表格实例 $scope.dtInstance = {}; $scope.dtOptions = DTOptionsBuilder .newOptions() .withOption('ajax', function (data, callback, settings) { settings.sAjaxDataProp = 'trans'; Module.fetchSalesData({ draw: data.draw, length: data.length, start: data.start, search : data.search.value, count_again : $scope.countAgain, startdate: $filter('date')($scope.item.startdate, 'yyyy-MM-dd'), enddate : $filter('date')($scope.item.enddate, 'yyyy-MM-dd'), payee_id: $scope.item.payee_id, staff_id: $scope.item.staff_id, order: data.order }).then(function(res) { $scope.payment_methods = res.data; // 销毁已存在的表格实例 if ($scope.dtInstance.DataTable) { $scope.dtInstance.DataTable.destroy(); } // 重置并更新列集合 $scope.dtColumns = [ DTColumnBuilder.newColumn('invoice_date') .withTitle('Date') .withOption('sWidth', '10%'), DTColumnBuilder.newColumn('ref_num').withTitle('Description') ]; angular.forEach($scope.payment_methods, function (value) { $scope.dtColumns.push( DTColumnBuilder.newColumn(value).withTitle(value) .notSortable().withClass('text-right') .withOption('stateSave', true) .renderWith(function (data, type, full) { data = typeof data === 'undefined' ? '0.00' : data; return $filter('currency')(data, ''); }) ); }); callback(res); $scope.countAgain = false; }) }) .withOption('serverSide', true); // 初始静态列 $scope.dtColumns = [ DTColumnBuilder.newColumn('invoice_date') .withTitle('Date') .withOption('sWidth', '10%'), DTColumnBuilder.newColumn('ref_num').withTitle('Description') ];
内容的提问来源于stack exchange,提问作者fife
相关产品推荐
相关产品推荐

