¿Cómo iterar sobre las claves y los valores con ng-repeat en AngularJS?

679

En mi controlador, tengo datos como: $scope.object = data

Ahora estos datos son el diccionario con claves y valores de json.

Puedo acceder al atributo con object.nameen la plantilla. ¿Hay alguna manera de que pueda iterar sobre las teclas también y mostrarlas en la tabla como

<tr><td> {{key}} </td> <td> data.key </td>

Los datos son así

{
    "id": 2,
    "project": "wewe2012",
    "date": "2013-02-26",
    "description": "ewew",
    "eet_no": "ewew",
}
usuario192362127
fuente

Respuestas:

1407

Qué tal si:

<table>
  <tr ng-repeat="(key, value) in data">
    <td> {{key}} </td> <td> {{ value }} </td>
  </tr>
</table>

Este método aparece en los documentos: https://docs.angularjs.org/api/ng/directive/ngRepeat

Josh David Miller
fuente
1
Debería funcionar: plnkr.co/edit/7AQF6k7hf2aZbWFmhVoX?p=preview . ¿Puedes modificar eso hasta que deje de funcionar?
Josh David Miller
2
Funciona a las mil maravillas. El único inconveniente es que se alfabetizará por las teclas, por lo que el nombre importa si el orden del artículo es relevante para la pantalla.
nombre para mostrar el
29
@IsabelHM Por muchas razones, muchos de nosotros recomendamos no iterar sobre objetos en un ngRepeat. De hecho, una vez escuché que un miembro del equipo central lamentaba haber implementado la capacidad de hacerlo. Por lo general, es mejor transformar el objeto en el controlador en una matriz; Esto aclara la intención y disminuye el riesgo de comportamiento extraño / impredecible en ciertos casos. Y puedes ordenar de la manera habitual. :-)
Josh David Miller
2
Como dijo IsabelHM, la salida se ordena alfabéticamente por el nombre. ¿Hay alguna manera de obligarlo a no hacerlo?
newman
44
@sethflowers Como mencioné en un comentario anterior, no recomiendo iterar sobre las claves de los objetos. Sería mejor convertirlo a una matriz en su controlador. Suponiendo que no hay manera de hacer esto idiomática basado en su modelo de negocio, ES6 hace que sea muy fácil: Object.getOwnPropertyNames(data).map(k => ({key:k, value:data[k]));.
Josh David Miller el
132

Si desea editar el valor de la propiedad con enlace bidireccional:

<tr ng-repeat="(key, value) in data">
    <td>{{key}}<input type="text" ng-model="data[key]"></td>
</tr>
cbk
fuente
2
¡Gracias! Por curiosidad, ¿encontraste esta técnica en documentos en algún lugar? Busqué en vano hasta encontrar tu respuesta aquí.
Roger
@cbk: Esto es lo que estaba buscando ... Gracias
JKA
Muchas gracias, me salvaste el día :)
Sergey
44
@cbk, ¿no es lo mismo que usar ng-model="value"?
Mike Harrison el
1
@MikeHarrison ng-repeatesencialmente está iterando sobre el objeto y devolviendo pares clave-valor. Piensa en ello como for(var value in arrayOfValues) { ... }. Si reasigna la variable valuedentro de su ciclo, no está cambiando lo que está dentro arrayOfValues, solo está volviendo a señalar valuea un nuevo objeto.
Jon Senchyna
12

No creo que haya una función incorporada en angular para hacer esto, pero puede hacerlo creando una propiedad de ámbito separada que contenga todos los nombres de encabezado, y puede completar esta propiedad automáticamente de esta manera:

var data = {
  foo: 'a',
  bar: 'b'
};

$scope.objectHeaders = [];

for ( property in data ) {
  $scope.objectHeaders.push(property); 
}

// Output: [ 'foo', 'bar' ]
Felipe Castro
fuente
1
Su respuesta funciona bien si uno necesita recorrer los datos dentro de un controlador angular (OP solicitó un bucle de vista).
Antonio Max
5

podemos seguir el siguiente procedimiento para evitar la visualización de valores-clave en orden alfabético.

Javascript

$scope.data = {
   "id": 2,
   "project": "wewe2012",
   "date": "2013-02-26",
   "description": "ewew",
   "eet_no": "ewew",
};
var array = [];
for(var key in $scope.data){
    var test = {};
    test[key]=$scope.data[key];
    array.push(test);
}
$scope.data = array;

HTML

<p ng-repeat="obj in data">
   <font ng-repeat="(key, value) in obj">
      {{key}} : {{value}}
   </font>
</p>
usuario3414423
fuente
Duplicar en palabra clave no alocado
amanuel2
4

Un ejemplo de lista de tareas que recorre objetos por ng-repeat:

var app = angular.module('toDolistApp', []);
app.controller('toDoListCntrl', function() {
  var self = this;
  self.toDoListItems = {};// []; //dont use square brackets if keys are string rather than numbers.
  self.doListCounter = 0;

  self.addToDoList = function() {		  		   
    var newToDoItem = {};
    newToDoItem.title     = self.toDoEntry;
    newToDoItem.completed = false;		   

    var keyIs = "key_" + self.doListCounter++;  		   

    self.toDoListItems[keyIs] = newToDoItem;		   
    self.toDoEntry = ""; //after adding the item make the input box blank.
  };
});

app.filter('propsCounter', function() {
  return function(input) {
    return Object.keys(input).length;
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="toDolistApp">    
  <div ng-controller="toDoListCntrl as toDoListCntrlAs">
    Total Items: {{toDoListCntrlAs.toDoListItems | propsCounter}}<br />
    Enter todo Item:  <input type="text" ng-model="toDoListCntrlAs.toDoEntry"/>
    <span>{{toDoListCntrlAs.toDoEntry}}</span>
    <button ng-click="toDoListCntrlAs.addToDoList()">Add Item</button> <br/>
    <div ng-repeat="(key, prop) in toDoListCntrlAs.toDoListItems"> 
      <span>{{$index+1}} : {{key}}   : Title = {{ prop.title}} : Status = {{ prop.completed}} </span>
    </div>     
  </div>    
</body>

Ashish Saxena
fuente
1
El comentario sobre no usar corchetes fue realmente útil. Ese cambio arregló mi código. Gracias.
Michael Khalili
Yo también. ¿Alguien puede explicar por qué el uso de llaves se corrigió mi código?
beingalex
1

Ejemplo completo aquí: -

<!DOCTYPE html >
<html ng-app="dashboard">
<head>
<title>AngularJS</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<link rel="stylesheet" href="./bootstrap.min.css">
<script src="./bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
</head>
<body ng-controller="myController">
    <table border='1'>
        <tr ng-repeat="(key,val) in collValues">
            <td ng-if="!hasChildren(val)">{{key}}</td>  
            <td ng-if="val === 'string'">
                <input type="text" name="{{key}}"></input>
            </td>
            <td ng-if="val === 'number'">
                <input type="number" name="{{key}}"></input>
            </td>
            <td ng-if="hasChildren(val)" td colspan='2'>
                <table border='1' ng-repeat="arrVal in val">
                    <tr ng-repeat="(key,val) in arrVal">
                        <td>{{key}}</td>    
                        <td ng-if="val === 'string'">
                            <input type="text" name="{{key}}"></input>
                        </td>
                        <td ng-if="val === 'number'">
                            <input type="number" name="{{key}}"></input>
                        </td>
                    </tr>
                </table>                
            </td>

        </tr>       
    </table>
</body>

<script type="text/javascript">

    var app = angular.module("dashboard",[]);
    app.controller("myController",function($scope){
        $scope.collValues = {
            'name':'string',
            'id':'string',
            'phone':'number',
            'depart':[
                    {
                        'depart':'string',
                        'name':'string' 
                    }
            ]   
        };

        $scope.hasChildren = function(bigL1) {
            return angular.isArray(bigL1);
} 
    });
</script>
</html>
Ajay Kumar
fuente
1
    Use below code it is working to display your key and value here is key start with 1:
         <tr ng-repeat="(key,value) in alert_list" >
                   <td>{{key +1}}</td>
                   <td>{{value.title}}</td>
                 </tr>
Below is document link for it. 

https://docs.angularjs.org/api/ng/directive/ngRepeat

Chirag Prajapati
fuente
0

Puede hacerlo en su javascript (controlador) o en su html (vista angular) ...

js:

$scope.arr = [];
for ( p in data ) {
  $scope.arr.push(p); 
}

html:

<tr ng-repeat="(k, v) in data">
    <td>{{k}}<input type="text" ng-model="data[k]"></td>
</tr>

Creo que la forma html es más angular, pero también puede hacerlo en su controlador y recuperarlo en su html ...

tampoco es una mala idea mirar las teclas de Objeto, te dan una serie de teclas si las necesitas, más información aquí:

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

Alireza
fuente
-2

Aquí hay un ejemplo de trabajo:

<div class="item item-text-wrap" ng-repeat="(key,value) in form_list">
  <b>{{key}}</b> : {{value}}
</div>

editado

Nakul Wali
fuente