AngularJS - як отримати ngRepeat відфільтровану посилання на результат


129

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

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

і я можу бачити винесені результати прекрасними; тепер я хочу запустити деяку логіку щодо цього результату в своєму контролері. Питання полягає в тому, як я можу схопити посилання на результати результатів?

Оновлення:


Просто для уточнення: я намагаюся створити автоматичне завершення, у мене є такий вхід:

<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>

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

Відповіді:


270

ОНОВЛЕННЯ : Ось простіший спосіб, ніж раніше.

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

Потім $scope.filteredItemsдоступний.


Дякую за відповідь, будь ласка, дивіться моє оновлення. Як би ти це реалізував, зауважи, що я переглядаю весь список предметів на init
Shlomi Schwartz

супер круто, дякую за це. Я б хотів, щоб це була вбудована функція NG
Shlomi Schwartz

3
Проблема такого підходу полягає в тому, що якщо ви переглядаєте призначену власність, ви закінчите спам $ digests (по одній ітерації) ... Можливо, є якийсь спосіб уникнути цього?
Juho Vepsäläinen

1
Якщо я переглядаю об’єкт пошуку та console.log, filteredItemsя завжди отримую дані один фільтр пізніше. Це не результат щойно зміненого фільтра, а той, що був попередній. Будь-які ідеї?
ProblemsOfSumit

4
Хтось може мені пояснити, чому це працює? Я можу зрозуміти, що змінна з області $ доступна в області повторення (спадкування області), але навпаки? Як? Деяка документація цінується. Спасибі
dalvarezmartinez1

30

Ось фільтрована версія рішення Енді Джосліна.

Оновлення: BREAKING CHANGE. Станом на версію 1.3.0-beta.19 ( ця фіксація ) фільтри не мають контексту і 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.


Дякую! Чи можете ви пояснити, як працює код фільтра? Я не знайомий з $ parse, і кутові документи не допомогли мені розшифрувати, як саме працює ваш фільтр.
Магне

2
@Magne Без проблем! Будь ласка, ознайомтеся з оновленням, хоча це може врятувати вам біль і страждання в дорозі. Коротше кажучи, щоб відповісти на ваше запитання, $parseце компілятор виразів Angular . Наприклад, він візьме рядок 'some.object.property' і поверне функцію, яка дозволяє вам встановити або отримати значення на вказаному шляху для заданого контекст. Я використовую його, щоб конкретно встановити результати фільтра на область $. Я сподіваюся, що це відповість на ваше запитання.
kevinjamesus86

23

Спробуйте щось подібне, проблема з ng-повтором полягає в тому, що він створює дочірню область, через що ви не можете отримати доступ

фільтритеми

від контролера

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

16

Оновлення:

Навіть після 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))">

Добре зауважити, що якщо у вас є обмежений фільтр щодо цього. Це не відображатиметься в $ parent.labelResults
Zack

Якщо я console.log labelResultsзавжди отримую дані один фільтр пізніше. Це не результат щойно зміненого фільтра, а той, що був попередній. У вас не було цієї проблеми?
Анна

10

Я придумав дещо кращу версію рішення Енді. У своєму рішенні ng-повтор ставить годинник на вираз, що містить завдання. Кожен цикл дайджесту оцінить це вираз і призначить результат змінній області.

Проблема цього рішення полягає в тому, що ви можете зіткнутися з проблемами присвоєння, якщо ви знаходитесь в області дитини. Це та сама причина, чому ви повинні мати крапку в ng-моделі .

Інше, що мені не подобається в цьому рішенні - це те, що воно поховає визначення відфільтрованого масиву десь у розмітці подання. Якщо він використовується у кількох місцях у вашому огляді чи контролері, він може заплутатися.

Більш просте рішення - просто помістити годинник у свій контролер на функцію, яка робить завдання:

$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>

Ось загадка, де це показано у більш складному сценарії.


Супер чисто і не забруднює структуру, приємно!
кузин

це рішення ідеально підходить для мене. Я використовував колекцію іонічного повтору замість повторення. Ось чому прийнята відповідь не спрацювала для мене
Лакшай

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.