如何从异步调用中填充ng-table的选择过滤器
如何从异步调用中填充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-
你可以通过自定义筛选器实现:
ngtable上标准选项筛选器的代码如下:
调用此数据时传递: filter-data="names($column)"
,ngtable会为您获取数据。我不知道为什么这不能使用外部资源。我敢打赌,它与$column和promise有关,正如你指出的那样。
我在我的代码中做了一个快速解决方法来避免这种情况。编写自己的选择筛选器模板,如:
在控制器中获取外部数据:
$scope.externaldata = Api.query(); // Your custom api call
它完美地工作,但我的数据上有id,所以不需要name函数。
我明白这个解决方案不是最优的。让我们看看是否有人在这里写了更多的东西,让我们茅塞顿开。甚至esvit有时也会来 😉
我有一个类似但稍微复杂一些的问题。我想要能够动态更新过滤器列表,因为它们应该只是在一个 $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”。