Reputation: 810
I am trying to filter ng-repeat, but am trying to use a function rather than an actual filter to filter the data. I was under the impression that something like this would work
<tr ng-repeat="(key, value) in dataObj| filter:dataFilter">
And define dataFilter as a scope function.
$scope.dataFilter = function (item) {
console.log(item);
return false
};
Obviously the filter is just a test, which I would have expected to log the items and also return false for everything (thus displaying nothing after the filter is done). However the filter doesn't seem to even be called because the log doesn't fire. I am unsure of what I am doing wrong. I want to try this method of using a function rather than an actual filter which needs to be injected.
Update with more code
Directive
(function () {
'use strict';
angular
.module('test')
.directive('myDirective', MyDirective);
function MyDirective() {
return {
templateUrl: 'test.html',
controllerAs: 'controller',
controller: 'MyController',
"scope":{
"dataObj" : '='
}
};
}
})();
Controller
(function () {
'use strict';
angular
.module('test')
.controller('MyController', MyController);
MyController.$inject = ['$scope'];
function MyController($scope) {
$scope.dataFilter = function (item) {
console.log(item);
return false
};
}
})();
test.html
<table>
<tr ng-repeat="(key, value) in dataObj | filter:dataFilter">
<td>{{key}}</td>
<td>{{(value}}</td>
</tr>
</table>
The above code does not call the dataFilter function at all. It appears that I have to call it as a function and possibly send it a parameter. For example if I do:
<tr ng-repeat="(key, value) in dataObj | filter:dataFilter()">
The console will log "undefined" a number of times equal to the number of items in dataObj. (obvious since there was no parameter passed in). But what is perplexing is that even though I didn't pass any data in or do any real filtering, i would still expect that the view should not print out any data at all because the dataFilter() is returning false (as a test of course). Yet all the data is printed out in .
Overall issue
The function as a filter doesn't seem to work at all, even when actually called. I expected that a function that returns false should mean that the ng-repeat will "filter" (skip) that particular item.
The second issue is how to actually send the current "item" to the dataFilter function. I have tried sending key and value, but neither of them are defined.
Upvotes: 2
Views: 216
Reputation: 4953
It's not possible to use the standard $filter service on an object, it must be an array - the documentation is quite clear. I am unsure why you are not getting an error like this - note the link gives an example of how to implement a custom filter than operates on an object, which is what you want.
Use ng-if, ng-switch etc. to control ng-repeat flow. Your assumption regarding $filter results affecting ng-repeat iteration is misplaced.
Regardless of what some might say, it's totally OK to filter an object (as opposed to an array) but as noted above that requires a custom filter, which you state you don't want, so you're left with no solution given your requirements.
Here's a fiddle that is as good as it gets without a custom filter. You have to supply an array.
<div ng-controller="myController">
<table>
<tr ng-repeat="(item,result) in model | filter:myfilter"
ng-if="result">
<td>{{result.key}}=</td>
<td>{{result.value}}</td>
</tr>
</table>
</div>
Note above for clarity it's (item,result) not (key,value). Here's the code.
var myApp = angular.module('myApp', []);
myApp.controller('myController', ['$scope', function($scope) {
// You cannot pass standard $filter an object. It MUST be an array.
var obj = {
pi: 3.14,
aqua: "teen",
then: new Date(),
hunger: "force",
}
$scope.model = [];
for (var key in obj) {
if (obj.hasOwnProperty(key))
$scope.model.push({
key: key,
value: obj[key]
})
}
$scope.myfilter = function(item, index) {
console.log(item.key + " = " + item.value)
if (index % 2 == 0)
return undefined;
return item;
}
}]);
Upvotes: 0