AngularJS - cómo obtener una referencia de resultados filtrados ngRepeat


Estoy usando una directiva ng-repeat con filtro así:

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

Y puedo ver los resultados renderizados bien; ahora quiero ejecutar un poco de lógica en ese resultado en mi controlador. La pregunta es ¿cómo puedo obtener la referencia de los elementos de resultado?

Actualización:


Solo para aclarar: Estoy tratando de crear un autocompletado, tengo esta entrada:

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

Y luego los resultados filtrados:

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

Ahora quiero navegar por el resultado y seleccionar uno de los elemento.

Author: Damjan Pavlica, 2012-07-30

6 answers

ACTUALIZACIÓN: Esta es una forma más fácil que la que había antes.

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

Entonces $scope.filteredItems es accesible.

 257
Author: Andrew Joslin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-27 15:23:07

Aquí está la versión de filtro de la solución de Andy Joslin.

Actualización: CAMBIO RADICAL. A partir de la versión 1.3.0-beta.19 (esta confirmación) los filtros no tienen un contexto y this estarán vinculados al ámbito global. Puede pasar el contexto como argumento o usar la nueva sintaxis de aliasing en 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);
  };
});

Entonces, en su opinión

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

, Que le da acceso a $scope.filteredItems.

 30
Author: kevinjamesus86,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-15 16:37:34

Intente algo como esto, el problema con ng-repeat es que crea un ámbito hijo debido a que no puede acceder

Filteritems

Del controlador

<li ng-repeat="doc in $parent.filteritems = (docs | filter:searchitems)" ></li>
 21
Author: imal hasaranga perera,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-24 16:02:33

Actualización:

Incluso después de 1.3.0. si desea ponerlo en el ámbito del controlador o del padre, no puede hacerlo con como sintaxis. Por ejemplo si tengo el siguiente código:

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

Lo anterior no funcionará. La forma de rodearlo es usando el parent parent de la siguiente manera:

<li ng-repeat="label in ($parent.labelResults = (labels | filter:query))">
 14
Author: Gal Bracha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-07 15:06:39

Se me ocurrió una versión algo mejor de la solución de Andy. En su solución ng-repeat coloca una vigilancia en la expresión que contiene la asignación. Cada bucle digest evaluará esa expresión y asignará el resultado a la variable scope.

El problema con esta solución es que puede tener problemas de asignación si está en un ámbito secundario. Esta es la misma razón por la que debería tener un punto en ng-model.

La otra cosa que no me gusta de esta solución es que entierra la definición de la matriz filtrada en algún lugar del marcado de la vista. Si se usa en varios lugares de su vista o su controlador, puede ser confuso.

Una solución más simple es simplemente colocar un reloj en su controlador en una función que realiza la asignación:

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

Esta función será evaluada durante cada ciclo de digest por lo que el rendimiento debe ser comparable con la solución de Andy. También puede agregar cualquier número de asignaciones en la función para mantenerlas todas en un lugar en lugar de dispersos por la vista.

En la vista, solo usaría la lista filtrada directamente:

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

Aquí hay un violín donde esto se muestra en un escenario más complicado.

 10
Author: Dave Johnson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:36

Comprueba esta respuesta:

Seleccionar y acceder a elementos en ng-repeat

<li ng-repeat="item in ..." ng-click="select_item(item)">
 -2
Author: Simon De Uvarow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:36