How to populate select filters on ng-table from async call
I had a similar but slightly more complex issue. I wanted to be able to update the list of filters dynamically which seemed totally doable since they should just in a $scope variable anyway. Basically, I expected that, if I have $scope.filterOptions = [];
then I could set filter-data="filterOptions"
and any update to that list would be automatically reflected. I was wrong.
But I found a solution that I think is pretty good. First, you need to override the ngTable select filter template (in case you don't know how to do this, it involves using $templateCache
and the key you need to override is 'ng-table/filters/select.html'
).
In the normal template, you'll find something like this ng-options="data.id as data.title for data in $column.data"
and the problem with that is that $column.data
is a fixed value that won't change when we update $scope.filterOptions
.
My solution is to pass only the $scope key as filter-data instead of passing the whole list of options. So, instead of filter-data="filterOptions"
, I'll pass filter-data="'filterOptions'"
and then, put a small change in the template like: ng-options="data.id as data.title for data in {{$column.data}}"
.
Obviously, this is a significant change to how the select filter works. In my case, it was for a very small app that only had one table but you may be concerned that a change like this will break your other selects. If that's the case, you may want to build this solution into a custom filter instead of just overriding 'select'.
You can achieve that with a custom filter:
The code for the standard select filter on ngtable says:
<select ng-options="data.id as data.title for data in column.data" ng-model="params.filter()[name]" ng-show="filter == 'select'" class="filter filter-select form-control" name="{{column.filterName}}"></select>
When you call this data you pass: filter-data="names($column)"
and ngtable takes care of getting the data for you. I don't know why this does not work with an external resource. I bet it has something to do with the $column and the promise, as you pointed out.
I did a quick workaround in my code to avoid that. Writing my own select filter template like:
<select id="filterTest" class="form-control" ng-model="tableParams.filter()['test']" ng-options="e.id as e.title for e in externaldata"></select>
You fetch this externaldata in your controller:
$scope.externaldata = Api.query(); // Your custom api call
It works perfectly, but I do have an id
on my data, so no need of the name
function.
I understand this solution is not optimal. Let's see if somebody writes here more than this 'workaround' and enlightens us. Even esvit is here sometimes ;)
This works for me:
HTML:
<td data-title="'Doc type'" filter="{ 'doc_types': 'select' }" filter-data="docTypes()" sortable="'doc_types'"> {{task.doc_type}}</td>
AngularJS:
$scope.docTypes = function ($scope) { var def = $q.defer(); //var docType = [ // {'id':'4', 'title':'Whatever 1'}, // {'id':'9', 'title':'Whatever 2'}, // {'id':'11', 'title':'Whatever 3'} //]; // Or get data from API. // Format should be same as above. var docType = $http.get('http://whatever.dev', { params: { param1: data1 } }); //Or with Restangular var docType = Restangular.all('/api/doctype').getList(); def.resolve(docType); return def;};