web-dev-qa-db-fra.com

Angular ng-repeat avec des objets JSON imbriqués?

J'ai un objet JSON, représenté comme tel:

 {
  "orders" : [
    {
      "ordernum" : "PRAAA000000177800601",
      "buyer" : "Donna Heywood"
      "parcels" : [
        {
          "upid" : "UPID567890123456",
          "tpid" : "TPID789456789485"
        },
        {
          "upid" : "UPID586905486090",
          "tpid" : "TPID343454645455"          
        }
      ]
    },
    {
      "ordernum" : "ORAAA000000367567345",
      "buyer" : "Melanie Daniels"
      "parcels" : [
        {
          "upid" : "UPID456547347776",
          "tpid" : "TPID645896579688"
        },
        {
          "upid" : "UPID768577673366",
          "tpid" : "TPID784574333345"
        }
      ]
    }
  ]
}

J'ai besoin de faire un répéteur au second niveau de ceci, une liste des nombres "upid".

Je sais déjà comment obtenir le plus haut niveau

<li ng-repeat="o in orders">{{o.ordernum}}</li>

Mais je ne suis pas clair sur la séquence pour boucler un niveau. Par exemple, c'est faux:

<li ng-repeat="p in orders.parcels">{{p.upid}}</li>

Je sais aussi comment imbriquer des répéteurs pour l'obtenir, mais dans ce cas, je n'ai pas du tout besoin d'afficher le niveau supérieur.

CLARIFICATION

Le but ici est d’avoir une liste avec les 4 numéros "upid" (il y en a 2 pour chaque colis, et il y a 2 colis dans la commande).

10
Steve

Rechercher beaucoup pour une solution simple et agréable pour une itération dynamique. Je suis venu avec ça

JAVASCRIPT (angulaire): une personne est un exemple d'objet imbriqué. la fonction is_object sera utilisée dans la vue HTML.

$scope.person = {
    "name": "john",
    "properties": {
       "age": 25,
       "sex": "m"
    },
    "salary": 1000
}

// helper method to check if a field is a nested object
$scope.is_object = function (something) {
    return typeof (something) == 'object' ? true : false;
};

HTML: définit un modèle pour un tableau simple. le 1er TD est la touche affichée. un autre TD (2 ou 3, mais jamais les deux) affichera la valeur si ce n'est pas un objet (nombre/chaîne), OR boucle à nouveau s'il s'agit d'un objet.

<table border="1">
<tr ng-repeat="(k,v) in person">
    <td> {{ k }} </td>
    <td ng-if="is_object(v) == false"> {{ v }} </td>
    <td ng-if="is_object(v)">
        <table border="1">
            <tr ng-repeat="(k2,v2) in v">
                <td> {{ k2 }} </td>
                <td> {{ v2 }} </td>
            </tr>
        </table>
    </td>
</tr>
</table>
0
chenchuk

En fait, c'est la même réponse de @sylwester. La meilleure façon de le mettre dans filter. Et vous pouvez le réutiliser en passant le paramètre propertyName. 

Dans votre cas, nous avons passé parcels

JS

myApp.filter('createarray', function () {
    return function (value, propertyName) {
        var arrayList = [];
        angular.forEach(value, function (val) {
            angular.forEach(val[propertyName], function (v) {
                arrayList.Push(v)
            });
        });
        return arrayList;
    }
});

HTML

<ul>
    <li ng-repeat="o in ordersList.orders | createarray: 'parcels'">{{o.upid}}</li>
</ul>

Voici en train de travailler Fiddle

5
Pankaj Parkar

Vous pouvez simplement créer un nouveau tableau 'colis' comme dans la démo ci-dessous:

var app = angular.module('app', []);
app.controller('homeCtrl', function($scope) {
  $scope.data = {
    "orders": [{
      "ordernum": "PRAAA000000177800601",
      "buyer": "Donna Heywood",
      "parcels": [{
        "upid": "UPID567890123456",
        "tpid": "TPID789456789485"
      }, {
        "upid": "UPID586905486090",
        "tpid": "TPID343454645455"
      }]
    }, {
      "ordernum": "ORAAA000000367567345",
      "buyer": "Melanie Daniels",
      "parcels": [{
        "upid": "UPID456547347776",
        "tpid": "TPID645896579688"
      }, {
        "upid": "UPID768577673366",
        "tpid": "TPID784574333345"
      }]
    }]
  };

  $scope.parcels = [];
  angular.forEach($scope.data.orders, function(order) {
    angular.forEach(order.parcels, function(parcel) {
      $scope.parcels.Push(parcel)
    })
  })
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <div ng-controller="homeCtrl">

    <ul>
      <li ng-repeat="o in parcels">{{o.upid}}</li>
    </ul>

  </div>
</div>

5
sylwester

On dirait que vous avez juste besoin d'un double imbriqué pour la boucle - 

<ul>    
  <div ng-repeat="o in orders">
    <li ng-repeat="p in o.parcels">{{p.upid}}</li>
  </div>
</ul>

Le code HTML est peut-être un peu moche ici, mais je ne sais pas exactement ce que vous voulez faire Sinon, vous pouvez simplement créer un nouveau tableau de la parcels via mapping.

4
David Grinberg

La raison pour laquelle <li ng-repeat="p in orders.parcels">{{p.upid}}</li> ne fonctionne pas comme prévu est que le tableau colis est un objet de chaque commande individuelle de votre tableau d'ordre, c'est-à-dire qu'il ne s'agit pas d'un objet du tableau d'ordre lui-même. 

Si votre tableau de commandes est défini sur la portée $ d'un contrôleur, vous créez le tableau sur la variable $scope:

$scope.allParcels = $scope.orders
    .map(function (elem) {
         return elem.parcels;
    }) // get an array where each element is an array of parcels.
    .reduce(function (previousValue, currentValue) {
        return previousValue.concat(currentValue);
     }); // concat each array of parcels into a single array of parcels

puis sur le modèle, vous pouvez utiliser <li ng-repeat='p in allParcels'>{{p.upid}}</li> 

Si, toutefois, vous ne voulez pas placer le tableau sur le $scope, je pense que vous pouvez faire quelque chose de similaire à ceci:

<li ng-repeat="p in orders
     .map(function (elem) {
         return elem.parcels; 
      })
     .reduce(function (previousValue, currentValue) {
          return previousValue.concat(currentValue);
     })">{{p.upid}}</li>

bien que je ne sois pas sûr à 100% que Angular évalue le .map/.reduce dans l'expression ng-repeat (il est également mal avisé de générer un tableau de cette manière dans un ng-repeat, car angular tableau via carte/réduire à chaque cycle $digest).

0
Brian Law