2012-07-30 4 views
119

Я использую директиву нг-повтор с фильтром, как так:AngularJS - как получить ngRepeat отфильтрованной ссылку результата

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> 

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

ответ

245

ОБНОВЛЕНИЕ: Вот более простой способ, чем то, что было раньше.

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

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

+0

Спасибо за ответ, смотрите мое обновление. Как бы вы это реализовали, обратите внимание, что я получаю список всех элементов в init –

+0

Хорошо, обновил его. –

+0

супер классный, спасибо за это. Хотелось бы, чтобы это была встроенная функция NG –

29

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

Обновление: BREAKING CHANGE. Начиная с версии 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.

+0

Спасибо! Не могли бы вы объяснить, как работает код фильтра?Я не знаком с $ parse, и угловые документы не помогли мне декодировать, как работает ваш фильтр. – Magne

+2

@Magne Нет проблем! Пожалуйста, проверьте обновления, хотя это может сэкономить вам немного боли и страдания по дороге. Чтобы ответить на ваш вопрос, короче говоря, '$ parse' - это компилятор выражения Angular's (https://docs.angularjs.org/api/ng/service/$parse). Например, это займет строка ' some.object.property 'и вернуть функцию, которая позволяет либо установить, либо получить значение по указанному пути для указанного контекста. Я использую его для установки результатов фильтрации в области $ здесь, в частности. Надеюсь, это ответит на ваш вопрос. – kevinjamesus86

10

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

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

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

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

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

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

По мнению, вы бы просто использовать отфильтрованный список непосредственно:

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

Here's a fiddle where this is shown in a more complicated scenario.

+0

Супер чистый и не загрязняет структуру, хорошо! – kuzyn

+0

это решение идеально подходит для меня .. я использовал ионный сборник повторять вместо ng repeat..thats почему принятый ответ не работал для меня – Lakshay

+0

Большое спасибо ... это только спасло меня. –

21

попробовать что-то вроде этого, проблема с нг-повтором в том, что он создает дочернюю сферу из-за того, что вы не можете получить доступ к

filteritems

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

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

Обновление:

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

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

выше будет не работы. путь вокруг него с помощью $ родителя, как так:

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

Приятно отметить, что если у вас есть limitTo фильтр на этом. Он не будет отражен в $ parent.labelResults – Zack

+0

Если я 'console.log labelResults', я всегда получаю данные по одному фильтру позже. Это не результат только что измененного фильтра, а тот, который был из предыдущего изменения. У вас не было этой проблемы? – Anna