如何从异步调用中填充ng-table的选择过滤器

13 浏览
0 Comments

如何从异步调用中填充ng-table的选择过滤器

tl:dr

如何使用ajax/json来填充包括\'select\'筛选器的ng-table?

Plunk: http://plnkr.co/Zn09LV演示问题


详细

我正在尝试掌握AngualrJS和ng-table扩展,虽然我可以使用javascript中定义的静态数据获得一些漂亮的带有工作筛选器的表格,但是当我尝试将真实数据加载到表格中时就会遇到麻烦。

ng-table的主体被正确地填充,只要我只使用文本筛选器,一切似乎都正常:

            {{user.Name}}

 

工作正常。

但是,如果我更新以使用选择筛选器:

            {{user.Name}}

 

我遇到了同步问题,因为Names变量总是在数据从服务器返回之前评估。(可能在发送请求到服务器之前评估Names变量。)这意味着我得到一个空的列表,以供筛选器使用。

一旦数据从服务器返回,我似乎找不到一种方法来更新选择筛选器。重新运行最初创建筛选器列表的代码似乎没有效果。我不确定如何触发ng-table重新检查它的筛选器,以便不读取更新的变量。

我还无法想出一种方法来推迟变量的评估,直到异步调用完成。

对于我的javascript,我几乎使用了ng-table GitHub页面的示例ajax代码,并添加了选择过滤器的示例代码。

    $scope.tableParams = new ngTableParams({
        page: 1,            // show first page
        count: 10,          // count per page
        sorting: {
            name: 'asc'     // initial sorting
        }
    }, {
        total: 0,           // length of data
        getData: function($defer, params) {
            // ajax request to api
            Api.get(params.url(), function(data) {
                $timeout(function() {
                    // update table params
                    var orderedData = params.sorting ?
                    $filter('orderBy')(data.result, params.orderBy()) :
                    data.result;
                    orderedData = params.filter ?
                    $filter('filter')(orderedData, params.filter()) :
                    orderedData;
                    $scope.users = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count());
                    params.total(orderedData.length); // set total for recalc pagination
                    $defer.resolve($scope.users);
                }, 500);
            });
        }
    });
    var inArray = Array.prototype.indexOf ?
    function (val, arr) {
        return arr.indexOf(val)
    } :
    function (val, arr) {
        var i = arr.length;
        while (i--) {
            if (arr[i] === val) return i;
        }
        return -1
    };
$scope.names = function(column) {
    var def = $q.defer(),
        arr = [],
        names = [];
    angular.forEach(data, function(item){
        if (inArray(item.name, arr) === -1) {
            arr.push(item.name);
            names.push({
                'id': item.name,
                'title': item.name
            });
        }
    });
    def.resolve(names);
    return def;
};

我尝试了几次添加额外的$q.defer()并在初始数据获取后包装$scope.names函数的代码,但是我对promise和defer的理解不够强,无法使任何东西起作用。

在GitHub上有一些说明,提示ng-table中存在一个bug,但我不确定这是否属实,或者我是在做一些愚蠢的事情。

https://github.com/esvit/ng-table/issues/186

对于如何继续处理此问题的指导将不胜感激。

-Kaine-

admin 更改状态以发布 2023年5月24日
0
0 Comments

你可以通过自定义筛选器实现:

ngtable上标准选项筛选器的代码如下:


调用此数据时传递: filter-data="names($column)",ngtable会为您获取数据。我不知道为什么这不能使用外部资源。我敢打赌,它与$column和promise有关,正如你指出的那样。

我在我的代码中做了一个快速解决方法来避免这种情况。编写自己的选择筛选器模板,如:


在控制器中获取外部数据:

$scope.externaldata = Api.query(); // Your custom api call

它完美地工作,但我的数据上有id,所以不需要name函数。

我明白这个解决方案不是最优的。让我们看看是否有人在这里写了更多的东西,让我们茅塞顿开。甚至esvit有时也会来 😉

0
0 Comments

我有一个类似但稍微复杂一些的问题。我想要能够动态更新过滤器列表,因为它们应该只是在一个 $scope 变量中。基本上,我期望如果我有 $scope.filterOptions = [];,那么我可以设置 filter-data="filterOptions",并且对该列表的任何更新都将自动反映。但我错了。

但我找到了一个我认为相当不错的解决方案。首先,您需要覆盖 ngTable 选择过滤器模板(如果您不知道如何做到这一点,那么它涉及使用 $templateCache,您需要覆盖的关键字是 'ng-table/filters/select.html')。

在正常的模板中,您将找到类似于 ng-options="data.id as data.title for data in $column.data" 的内容,问题在于 $column.data 是一个固定的值,当我们更新 $scope.filterOptions 时不会改变。

我的解决方案是仅传递 $scope 的 key 作为 filter-data,而不是传递整个选项列表。因此,我将传递 filter-data="'filterOptions'",然后在模板中进行小改动,例如: ng-options="data.id as data.title for data in {{$column.data}}"

显然,这是对选择过滤器的工作方式进行了重大改变。在我的情况下,这是针对一个只有一个表的非常小的应用程序,但是您可能会担心这样的改变会破坏您其他的选择。如果是这种情况,您可能希望将此解决方案构建到自定义过滤器中,而不仅仅是覆盖“select”。

0