AngularJS中使用smart-table预过滤行数据的技术问题
Smart-Table 预过滤集合无需创建副本的解决方案
问题描述
我希望在smart-table中预过滤要展示的对象集合,出于内存占用考虑,不想在控制器中创建表格的过滤副本。过滤逻辑为将行ID转为数字并判断是否大于0,已在控制器中定义filterIdGTZ方法:
app.controller("MyCtrl", ['$scope', '$http', '$sce', function ($scope, $http, $sce) { app.sources = []; // 动态加载的数据 app.filterIdGTZ = function (rowobj) { return Number(rowobj.id) > 0; } }
尝试了三种过滤方式均未成功:
- 在st-table上添加过滤:
<table st-table="displayedSources | filter: app.filterIdGTZ" st-safe-src="app.sources" class="table table-striped align-middle">
- 在st-safe-src上添加过滤:
<table st-table="displayedSources" st-safe-src="app.sources | filter: app.filterIdGTZ" class="table table-striped align-middle">
- 在
<tr>的ng-repeat中添加过滤,但破坏了客户端分页,显示行数不符合预期:
<tr ng-repeat="source in displayedSources | filter: app.filterIdGTZ">
是否必须创建过滤副本?但这样会带来后续同步原表格与过滤副本的诸多问题。
解决方案
不需要创建过滤副本,有两种靠谱的方法能实现需求,既不额外占用内存,也能保证smart-table的分页、排序功能正常工作:
方法1:监听原数据源实时生成过滤子集
在控制器里通过$watch监听原数据源的变化,一旦数据更新就实时过滤出符合条件的子集——这里的子集是原数组中对象的引用,不会额外创建新对象,内存占用极低:
app.controller("MyCtrl", ['$scope', '$http', '$sce', function ($scope, $http, $sce) { app.sources = []; // 动态加载的数据 // 预过滤逻辑 app.filterIdGTZ = function (rowobj) { return Number(rowobj.id) > 0; }; // 初始化显示数组 $scope.displayedSources = []; // 监听原数据源变化,实时过滤 $scope.$watch('app.sources', function(newData) { if (newData && newData.length) { // 直接过滤原数组,返回符合条件的对象引用子集 $scope.displayedSources = newData.filter(app.filterIdGTZ); } }, true); // 深度监听,确保数组内对象变化也能触发 }
模板里正常绑定即可,smart-table能正确识别displayedSources并处理分页排序:
<table st-table="displayedSources" st-safe-src="app.sources" class="table table-striped align-middle"> <tr ng-repeat="source in displayedSources"> <!-- 表格内容 --> </tr> </table>
方法2:注册自定义AngularJS过滤器
注册一个全局的自定义过滤器,直接在st-safe-src中使用,AngularJS会自动处理数据源变化后的过滤,同样返回原对象的引用子集:
// 注册自定义过滤器 app.filter('filterIdGTZ', function() { return function(items) { if (!items) return []; return items.filter(function(rowobj) { return Number(rowobj.id) > 0; }); }; });
模板中直接在st-safe-src上应用自定义过滤器:
<table st-table="displayedSources" st-safe-src="app.sources | filterIdGTZ" class="table table-striped align-middle"> <tr ng-repeat="source in displayedSources"> <!-- 表格内容 --> </tr> </table>
为什么之前的方法失败?
- 第一种方式:
st-table绑定的变量不能直接带过滤器,因为smart-table需要直接操作这个变量来处理分页、排序,过滤器返回的是临时数组,无法被正确追踪。 - 第二种方式:
st-safe-src的作用是提供原始数据源,smart-table内部会基于它生成显示数组,直接加过滤器会导致smart-table无法识别原始数据的变化,同步逻辑失效。 - 第三种方式:在
ng-repeat中加过滤器会绕过smart-table的分页逻辑,分页计算的是未过滤的总数据量,所以显示行数不符合预期。
内容的提问来源于stack exchange,提问作者Cabu
相关产品推荐
相关产品推荐

