filter:notarray Expected array but received: 0
Solution 1
The problem is occurring because you are using track by $index
before you are applying your filter. To resolve this, change your expression to:
<li ng-repeat="g in graphs | filter:searchText track by $index"></li>
The track by
expression should always be at the last, after all your filters. Its a rule mentioned in the docs: ngRepeat
Explanation:
When you don't use track by $index
in ngRepeat
, the input for all the filters used is the array, that is, if its
ng-repeat="item in items | filter1 | filter2",
then items
is the input passed to the filters by default and the filtering is done on this input.
However, when you use track by $index
, the input to the filters becomes $index
instead of items
and therefore the error:
Expected array(read: items) but received 0(read: $index).
Therefore, to counter this, the array is first passed through all the filters and the filtered result is used with track by $index
.
Hope this clears it up.
Solution 2
You should always use track by
at the end of expression
<li ng-repeat="g in graphs | filter:searchText track by $index"></li>
Since while evaluating an expression for ng-repeat
angular needs the final result for track by to work. If you provide it at the end, your filter will be applied and track by
is computed on final output. You can see the source code at angular docs.
According to the documentation of ng-repeat
If you are working with objects that have an identifier property, you should track by the identifier instead of the whole object. Should you reload your data later, ngRepeat will not have to rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones. For large collections, this signifincantly improves rendering performance. If you don't have a unique identifier, track by $index can also provide a performance boost.
Related videos on Youtube
Saurabh Kumar
Updated on July 09, 2022Comments
-
Saurabh Kumar almost 2 years
controller
@RequestMapping(value = "/graphs", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public Collection<Graph> getSkeletonGraph() { log.debug("REST request to get current graphs"); return graphService.getSkeletonGraphs(); }
Angular call
$scope.graphs = []; Graph.getGraphs().$promise.then(function(result) { $scope.graphs = result; }); angular.module('sampleApplicationApp').factory('Graph', function($resource) { return { getGraphs: function() { return $resource('api/graphs/:id').query(); } }; })
I am not sure why using the filter i get the exception.
looked also in angular doc https://docs.angularjs.org/error/filter/notarray My result is array but not sure why I am getting such exception.
Sample result from backend i am getting.
[{"id":"135520b0-9e4b-11e5-a67e-5668957d0149","area":"Bingo","models":[],"enumerateds":[]},{"id":"0db925e0-9e53-11e5-a67e-5668957d0149","area":"jin","models":[],"enumerateds":[]},{"id":"7a717330-9788-11e5-b259-5668957d0149","area":"Product","models":[],"enumerateds":[]},{"id":"402d4c30-980f-11e5-a2a3-5668957d0149","area":"fgfgfg","models":[],"enumerateds":[]},{"id":"404b77b0-9e53-11e5-a67e-5668957d0149","area":"olah","models":[],"enumerateds":[]},{"id":"cd071b10-9e52-11e5-a67e-5668957d0149","area":"lolo","models":[],"enumerateds":[]},{"id":"d9808e60-9710-11e5-b112-5668957d0149","area":"catalog","models":[],"enumerateds":[]},{"id":"2aaca9f0-97e2-11e5-91cd-5668957d0149","area":"btg","models":[],"enumerateds":[]},{"id":"955e9ed0-978c-11e5-93fd-5668957d0149","area":"promotions","models":[],"enumerateds":[]},{"id":"1e441d60-980f-11e5-a2a3-5668957d0149","area":"hjuhh","models":[],"enumerateds":[]},{"id":"fb96dfe0-978d-11e5-93fd-5668957d0149","area":"voucher","models":[],"enumerateds":[]}]
html
<li ng-repeat="g in graphs track by $index | filter:searchText"></li>
-
Saurabh Kumar over 8 yearscould you please describe the logic behind your suggestion
-
Tarun Dugar over 8 yearsIts a rule mentioned in the docs. Filters should be applied before the track by expression. See in docs: docs.angularjs.org/api/ng/directive/ngRepeat
-
MacK about 8 yearsAfter spending 2 hours trying to figure out why the filter on the Angular website was working and mine wasn't this was the only answer which solved my problem! Needless to say I would probably need to open and read again the docs. However that's very anti-intuitive and the error doesn't help at all, why
track by $index
should be always the last expression? Makes no sense in my head. -
Tarun Dugar about 8 yearsThere is a reason for that. When you don't use
track by $index
, the input for all the filters is the array, that is, if itsitem in items
, items is the input passed to the filters. However, when you usetrack by $index
, the input to the filters becomes$index
instead ofitems
and therefore the error: Expected array(items
) but received 0($index
). Hope this clears it up. -
kishorekumaru about 6 yearsbrilliant, spent more than an hour
-
forresthopkinsa over 3 yearsThis should really be displayed much more prominently in the documentation