You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 05:28:09