Filter: notarray Ожидаемый массив, но полученный: 0

контроллер

    @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 вызов

    $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();
      }
     };
    })

Я не уверен, почему использование фильтра я получаю исключение.

посмотрел также в angular doc https://docs.angularjs.org/error/filter/notarray Мой результат - массив, но не уверен, почему я получаю такое исключение.

Пример результата из бэкэнд, который я получаю.

[{"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>

Ответ 1

Проблема возникает, потому что вы используете track by $index, прежде чем применять свой фильтр. Чтобы устранить это, измените ваше выражение на:

<li ng-repeat="g in graphs | filter:searchText track by $index"></li>

Выражение track by всегда должно быть последним, после всех ваших фильтров. Его правило, упомянутое в документах: ngRepeat

Объяснение:

Если вы не используете track by $index в ngRepeat, вход для всех используемых фильтров - это массив, то есть, если его

ng-repeat="item in items | filter1 | filter2", 

то items - это вход, переданный фильтрам по умолчанию, и фильтрация выполняется на этом входе.

Однако, когда вы используете track by $index, вход в фильтры становится $index вместо items и, следовательно, ошибка:

Ожидаемый массив (read: items), но полученный 0 (read: $index).

Поэтому, чтобы противостоять этому, массив сначала проходит через все фильтры, а результат фильтрации используется с track by $index.

Надеюсь, что это очистит.

Ответ 2

Вы всегда должны использовать track by в конце выражения

<li ng-repeat="g in graphs | filter:searchText track by $index"></li>

Поскольку при оценке выражения для ng-repeat angular требуется конечный результат для отслеживания для работы. Если вы предоставите его в конце, ваш фильтр будет применен, а track by будет вычислен на конечном выходе. Исходный код можно увидеть в angular docs.

Согласно документации ng-repeat

Если вы работаете с объектами, обладающими свойством идентификатора, вы должен отслеживать идентификатор вместо всего объекта. Тебе следует перезагрузите данные позже, ngRepeat не придется перестраивать DOM элементы для элементов, которые он уже выполнил, даже если JavaScript объекты в коллекции были заменены новыми. Для больших коллекций, это значительно улучшает производительность рендеринга. Если у вас нет уникального идентификатора, отслеживание по индексу $index также может обеспечивают повышение производительности.