AngularJS - как получить ссылку на результат фильтрации ngRepeat

Я использую директиву ng-repeat с фильтром следующим образом:

ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4"

и я вижу, что полученные результаты прекрасны; теперь я хочу запустить некоторую логику этого результата в моем контроллере. Вопрос в том, как я могу получить ссылку на результат?

Update:


Просто чтобы уточнить: я пытаюсь создать автоматическое завершение, у меня есть этот ввод:

<input id="queryInput" ng-model="query" type="text" size="30" placeholder="Enter query">

а затем отфильтрованные результаты:

<ul>
   <li  ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4">{{item.name}}</li>
</ul>

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

Ответ 1

ОБНОВЛЕНИЕ. Здесь проще, чем раньше.

 <input ng-model="query">
 <div ng-repeat="item in (filteredItems = (items | orderBy:'order_prop' | filter:query | limitTo:4))">
   {{item}}
 </div>

Тогда $scope.filteredItems доступен.

Ответ 2

Здесь версия фильтра решения Энди Хослина.

Обновление: РАЗРЕШЕНИЕ ИЗМЕНЕНИЯ. Начиная с версии 1.3.0-beta.19 (this commit) фильтры не имеют контекста, а this будет привязан к глобальной области. Вы можете передать контекст в качестве аргумента или использовать новый синтаксис псевдонимов в ngRepeat, 1.3.0-beta.17 +.

// pre 1.3.0-beta.19
yourModule.filter("as", function($parse) {
  return function(value, path) {
    return $parse(path).assign(this, value);
  };
});

// 1.3.0-beta.19+
yourModule.filter("as", function($parse) {
  return function(value, context, path) {
    return $parse(path).assign(context, value);
  };
});

Затем на ваш взгляд

<!-- pre 1.3.0-beta.19 -->
<input ng-model="query">
<div ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4 | as:'filteredItems'">
 {{item}}
</div>

<!-- 1.3.0-beta.19+ -->
<input ng-model="query">
<div ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4 | as:this:'filteredItems'">
 {{item}}
</div>

<!-- 1.3.0-beta.17+ ngRepeat aliasing -->
<input ng-model="query">
<div ng-repeat="item in items | orderBy:'order_prop' | filter:query | limitTo:4 as filteredItems">
 {{item}}
</div>

Что дает вам доступ к $scope.filteredItems.

Ответ 3

Попробуйте что-то подобное, проблема с ng-repeat заключается в том, что он создает дочернюю область, из-за которой вы не можете получить доступ к

filteritems

с контроллера

<li ng-repeat="doc in $parent.filteritems = (docs | filter:searchitems)" ></li>

Ответ 4

Update:

Даже после 1.3.0. если вы хотите поместить его в область действия контроллера или родителя, вы не можете сделать это с синтаксисом как. Например, если у меня есть следующий код:

<div>{{labelResults}}</div>
<li ng-repeat="label in (labels | filter:query | as labelResults)">
</div>

выше будет не работа. Способ обойти это с помощью $parent:

<li ng-repeat="label in ($parent.labelResults = (labels | filter:query))">

Ответ 5

Я придумал несколько лучшую версию решения Энди. В своем решении ng-repeat помещает часы на выражение, которое содержит задание. Каждый цикл дайджеста будет оценивать это выражение и присваивать результат переменной области.

Проблема с этим решением заключается в том, что вы можете столкнуться с проблемами присваивания, если находитесь в дочерней области. Это по той же причине, почему у вас должна быть точка в ng-модели.

Другим, что мне не нравится в этом решении, является то, что он зарывает определение фильтрованного массива где-то в разметке представления. Если он используется в нескольких местах в вашем представлении или вашем контроллере, он может запутаться.

Более простым решением является просто установить часы в контроллере на функцию, которая выполняет назначение:

$scope.$watch(function () {
    $scope.filteredItems = $scope.$eval("items | orderBy:'order_prop' | filter:query | limitTo:4");
});

Эта функция будет оцениваться в течение каждого цикла дайджеста, поэтому производительность должна быть сопоставима с решением Andy. Вы также можете добавить любое количество назначений в функцию, чтобы держать их всех в одном месте, а не разбросано по виду.

В представлении вы просто должны напрямую использовать отфильтрованный список:

<ul>
    <li  ng-repeat="item in filteredItems">{{item.name}}</li>
</ul>

Здесь сценарий, где это показано в более сложном сценарии.