filter:notarray Expected array but received: 0

21,206

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.

Share:
21,206

Related videos on Youtube

Saurabh Kumar
Author by

Saurabh Kumar

Updated on July 09, 2022

Comments

  • Saurabh Kumar
    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
    Saurabh Kumar over 8 years
    could you please describe the logic behind your suggestion
  • Tarun Dugar
    Tarun Dugar over 8 years
    Its 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
    MacK about 8 years
    After 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
    Tarun Dugar about 8 years
    There 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 its item in items, items is the input passed to the filters. However, when you use track by $index, the input to the filters becomes $index instead of items and therefore the error: Expected array(items) but received 0($index). Hope this clears it up.
  • kishorekumaru
    kishorekumaru about 6 years
    brilliant, spent more than an hour
  • forresthopkinsa
    forresthopkinsa over 3 years
    This should really be displayed much more prominently in the documentation