Tengo una matriz de datos que contiene muchos objetos (formato JSON). Se puede asumir lo siguiente como el contenido de esta matriz:
var data = [
{
"name": "Jim",
"age" : 25
},
{
"name": "Jerry",
"age": 27
}
];
Ahora, muestro estos detalles como:
<div ng-repeat="person in data | filter: query">
</div
Aquí, la consulta se modela a un campo de entrada en el que el usuario puede restringir los datos mostrados.
Ahora, tengo otra ubicación en la que muestro el recuento actual de personas/personas que se muestran, es decir, Showing {{data.length}} Persons
Lo que quiero hacer es que cuando el usuario busca una persona y los datos que se muestran se filtran según la consulta, el Showing...persons
también cambia el valor de las personas que se muestran actualmente. Pero no está sucediendo. Siempre muestra el total de personas en los datos en lugar de la filtrada. ¿Cómo obtengo el recuento de los datos filtrados?
Para Angular 1.3+ (créditos para @Tom)
Utilice una expresión de alias (Docs: Angular 1.3.0: ngRepeat , desplácese hacia abajo hasta la sección Argumentos):
<div ng-repeat="person in data | filter:query as filtered">
</div>
Para Angular antes de 1.3
Asigna los resultados a una nueva variable (por ejemplo, filtered
) y accede a ella:
<div ng-repeat="person in filtered = (data | filter: query)">
</div>
Muestra el número de resultados:
Showing {{filtered.length}} Persons
Fiddle a ejemplo similar . Los créditos van a Pawel Kozlowski
Para completar, además de las respuestas anteriores (realizar cálculos de personas visibles dentro del controlador), también puede realizar esos cálculos en su plantilla HTML como se muestra en el siguiente ejemplo.
Suponiendo que su lista de personas está en la variable data
y usted filtra a las personas utilizando el modelo query
, el siguiente código funcionará para usted:
<p>Number of visible people: {{(data|filter:query).length}}</p>
<p>Total number of people: {{data.length}}</p>
{{data.length}}
- imprime el número total de personas{{(data|filter:query).length}}
- imprime el número filtrado de personasNotaque esta solución funciona bien si desea usar datos filtrados solo una vezen una página. Sin embargo, si usa datos filtrados más de una vez, por ejemplo, para presentar elementos y mostrar la longitud de la lista filtrada, I sugeriría usar expresión de alias(descrita a continuación) para AngularJS 1.3+o la solución propuesta por @Wumms para la versión de AngularJS anterior a 1.3.
Nueva función en Angular 1.3
Los creadores de AngularJS también notaron ese problema y en la versión 1.3 (beta 17) agregaron una expresión de "alias" que almacenará los resultados intermedios del repetidor una vez que se hayan aplicado los filtros, por ejemplo.
<div ng-repeat="person in data | filter:query as results">
<!-- template ... -->
</div>
<p>Number of visible people: {{results.length}}</p>
La expresión de aliasevitará problemas de ejecución de varios filtros).
Espero que le ayudará.
La forma más fácil si tienes
<div ng-repeat="person in data | filter: query"></div>
Longitud de datos filtrados
<div>{{ (data | filter: query).length }}</div>
ngRepeat crea una copia de la matriz cuando aplica un filtro, por lo que no puede usar la matriz de origen para hacer referencia solo a los elementos filtrados.
En su caso, quizás sea mejor aplicar el filtro dentro de su controlador usando el $filter
service:
function MainCtrl( $scope, filterFilter ) {
// ...
$scope.filteredData = myNormalData;
$scope.$watch( 'myInputModel', function ( val ) {
$scope.filteredData = filterFilter( myNormalData, val );
});
// ...
}
Y luego usas la propiedad filteredData
en tu vista. Aquí hay un Plunker que funciona: http://plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview
Desde AngularJS 1.3 puedes usar alias:
item in items | filter:x as results
y en algún lugar:
<span>Total {{results.length}} result(s).</span>
Desde docs :
También puede proporcionar una expresión de alias opcional que luego almacenará los resultados intermedios del repetidor una vez que se hayan aplicado los filtros. Normalmente, esto se usa para mostrar un mensaje especial cuando un filtro está activo en el repetidor, pero el conjunto de resultados filtrados está vacío.
Por ejemplo: artículo en artículos | filtrar: x como resultados almacenará el fragmento de los elementos repetidos como resultados, pero solo después de que los elementos se hayan procesado a través del filtro.
También es útil tener en cuenta que puede almacenar múltiples niveles de resultados agrupando filtros
all items: {{items.length}}
filtered items: {{filteredItems.length}}
limited and filtered items: {{limitedAndFilteredItems.length}}
<div ng-repeat="item in limitedAndFilteredItems = (filteredItems = (items | filter:search) | limitTo:25)">...</div>
aquí hay un violín de demostración
Aquí está el ejemplo trabajado Ver en Plunker
<body ng-controller="MainCtrl">
<input ng-model="search" type="text">
<br>
Showing {{data.length}} Persons; <br>
Filtered {{counted}}
<ul>
<li ng-repeat="person in data | filter:search">
{{person.name}}
</li>
</ul>
</body>
<script>
var app = angular.module('angularjs-starter', [])
app.controller('MainCtrl', function($scope, $filter) {
$scope.data = [
{
"name": "Jim", "age" : 21
}, {
"name": "Jerry", "age": 26
}, {
"name": "Alex", "age" : 25
}, {
"name": "Max", "age": 22
}
];
$scope.counted = $scope.data.length;
$scope.$watch("search", function(query){
$scope.counted = $filter("filter")($scope.data, query).length;
});
});
Puedes hacerlo con 2 maneras . En plantilla y en Controlador . En la plantilla, puede establecer su matriz filtrada en otra variable, luego usarla como desee. Aquí está cómo hacerlo:
<ul>
<li data-ng-repeat="user in usersList = (users | gender:filterGender)" data-ng-bind="user.name"></li>
</ul>
....
<span>{{ usersList.length | number }}</span>
Si necesita ejemplos, vea los ejemplos/demos filtrados de AngularJs filtrados