Como iterar sobre as chaves e valores com ng-repeat no AngularJS?

679

No meu controlador, tenho dados como: $scope.object = data

Agora, esses dados são o dicionário com chaves e valores de json.

Eu posso acessar o atributo com object.nameno modelo. Existe alguma maneira que eu possa iterar sobre as teclas também e exibi-las na tabela como

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

Os dados são assim

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

Respostas:

1407

E se:

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

Este método está listado nos documentos: https://docs.angularjs.org/api/ng/directive/ngRepeat

Josh David Miller
fonte
1
Deve funcionar: plnkr.co/edit/7AQF6k7hf2aZbWFmhVoX?p=preview . Você pode modificar isso até que pare de funcionar?
Josh David Miller
2
Ele funciona como um encanto. O único problema é que ele será alfabetizado pelas teclas para que a nomeação seja importante se a ordem do item for relevante para a exibição.
nome de exibição
29
@IsabelHM Por muitas razões, muitos de nós recomendamos não fazer iterações sobre objetos em um arquivo ngRepeat. De fato, uma vez ouvi um membro da equipe principal se arrepender de ter implementado a capacidade de fazê-lo! Geralmente é melhor transformar o objeto no controlador em uma matriz; isso torna a intenção mais clara e diminui o risco de comportamento estranho / imprevisível em certos casos. E você pode classificar da maneira usual. :-)
Josh David Miller
2
Como IsabelHM disse, a saída é ordenada alfabeticamente pelo nome. Existe uma maneira de forçá-lo a não fazê-lo?
newman
4
@sethflowers Como mencionei em um comentário anterior, não recomendo a iteração sobre as chaves nos objetos. Seria melhor convertê-lo em uma matriz no seu controlador. Assumindo que não há maneira idiomática de fazer isso com base no seu modelo de negócio, ES6 torna muito fácil: Object.getOwnPropertyNames(data).map(k => ({key:k, value:data[k]));.
Josh David Miller
132

Se você deseja editar o valor da propriedade com ligação bidirecional:

<tr ng-repeat="(key, value) in data">
    <td>{{key}}<input type="text" ng-model="data[key]"></td>
</tr>
cbk
fonte
2
Obrigado! Por curiosidade, você encontrou essa técnica nos documentos em algum lugar? Eu procurei em vão até encontrar sua resposta aqui.
Roger
@cbk: Isto é o que eu estava procurando .. Obrigado
JKA
Muito obrigado, você salvou meu dia :)
Sergey
4
@ CBK não é o mesmo que usar ng-model="value"?
Mike Harrison
1
O @MikeHarrison ng-repeatestá essencialmente interagindo sobre o objeto e retornando pares de valores-chave. Pense nisso como for(var value in arrayOfValues) { ... }. Se você redesignar a variável valuedentro de seu loop, não estará alterando o que está dentro arrayOfValues, apenas apontando novamente valuepara um novo objeto.
Jon Senchyna
12

Eu não acho que exista uma função interna em angular para fazer isso, mas você pode fazer isso criando uma propriedade de escopo separada contendo todos os nomes de cabeçalho, e você pode preencher essa propriedade automaticamente assim:

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

$scope.objectHeaders = [];

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

// Output: [ 'foo', 'bar' ]
Felipe Castro
fonte
1
Sua resposta funciona bem se for necessário fazer um loop através dos dados dentro de um controlador angular (o OP solicitou um loop de visualização).
Antonio Max
5

podemos seguir o procedimento abaixo para evitar a exibição de valores-chave em ordem alfabética.

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>
user3414423
fonte
Duplicar na palavra-chave não permitida
amanuel2 17/06
4

Um exemplo de lista de tarefas que faz um loop sobre o objeto 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
fonte
1
O comentário sobre não usar colchetes foi realmente útil. Essa mudança corrigiu meu código. Obrigado.
Michael Khalili
Eu também. Alguém pode explicar por que o uso de colchetes corrigiu meu código?
beingalex
1

Exemplo completo aqui: -

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

Você pode fazê-lo no seu javascript (controlador) ou no seu 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>

Eu acredito que a maneira html é mais angular, mas você também pode fazer no seu controlador e recuperá-lo no seu html ...

também não é uma má idéia olhar para as chaves de objeto, elas fornecem uma matriz de chaves, se você precisar delas, mais informações aqui:

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

Alireza
fonte
-2

Aqui está um exemplo de trabalho:

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

editado

Nakul Wali
fonte