2015-02-02 13 views
10

Ich habe ein JSON-Objekt, als solche dargestellt werden:Angular ng-repeat mit verschachtelten Json-Objekten?

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

Ich brauche einen Repeater auf der zweiten Ebene diesen, eine Liste der „UPID“ Zahlen zu tun.

Ich weiß schon, wie das Top-Level zu bekommen

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

Aber ich bin ein Niveau auf der Sequenz zu einer Schlaufe unklar. Zum Beispiel ist dies falsch:

Ich weiß auch, wie man Nest Repeater diese zu bekommen, aber in diesem Fall muss ich gar nicht die oberste Ebene angezeigt werden soll.

KLARSTELLUNG

Das Ziel ist hier eine Liste zu haben, mit den 4 „UPID“ Zahlen (es gibt 2 für jedes Paket, und es gibt zwei Pakete in der Reihenfolge).

Antwort

0

Suchen Sie viel nach einer schönen und einfachen Lösung, um dynamisch zu iterieren. Ich kam mit dieser

JAVASCRIPT (eckig): eine Person ist ein Beispiel für verschachtelte Objekte. Die is_object-Funktion wird in der HTML-Ansicht verwendet.

$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: Definieren Sie eine Vorlage für einfache Tabelle. Der 1. TD ist der Schlüssel, der angezeigt wird. ein anderer TD (2 oder 3, aber nie beide) zeigt den Wert, wenn es kein Objekt (Nummer/String) ist, ODER Schleife erneut, wenn es ein Objekt ist.

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

Scheinen, wie Sie gerade ein zwei verschachtelten for-Schleife müssen -

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

Die HTML könnte hier ein wenig hässlich sein, aber ich bin mir nicht sicher, was genau Sie sich für. Alternativ können Sie auch ein neues Array des parcels über Mapping erstellen.

+0

Diese Antwort würde mir 2 ul geben, jeder mit 2 LIs. – Steve

+0

Ich suche nach einem UL mit den 4 Paketen. – Steve

+0

@Steve Wie ich schon sagte, ich weiß nicht, wie genau Sie die Ausgabe wollen. Außerdem haben Sie immer die Möglichkeit, einem neuen Array zuzuordnen. –

5

Sie können wie in Demo unter neuen Array ‚Pakete‘ erstellen:

var app = angular.module('app', []); 
 
app.controller('homeCtrl', function($scope) { 
 
    $scope.data = { 
 
    "orders": [{ 
 
     "ordernum": "PRAAA000000177800601", 
 
     "buyer": "Donna Heywood", 
 
     "parcels": [{ 
 
     "upid": "UPID56789", 
 
     "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>

+0

Dies funktioniert nicht mit den Daten extern geladen werden, siehe http://plnr.co/edit/2WnMcwxcmTVA8luquWM9? p = Vorschau seit '$ scope.data.orders' existiert dann nicht. Ich lade die Bestellungen über eine Fabrik. – Steve

+0

Dies funktioniert auch dann noch, wenn Daten von einer Fabrik geladen werden. Sie müssten das neue Array nur zuordnen, wenn die Daten eintreffen. Behalten Sie die Bereichsvariable gleich bei, und ändern Sie dann diese Variable in das neue Array, wenn die Daten eingehen. Edit: Dies ist der beste Weg, dies zu tun. Die anderen Antworten sind unnötig schwer und/oder arbeiten nicht. – ribsies

+0

@Steve bitte siehe http://plnr.co/edit/FXpgRDqQTAm6QUstI86z?p=preview – sylwester

0

Der Grund, dass nicht wie erwartet funktioniert, weil die Pakete Array ist ein Objekt innerhalb jeder einzelnen Order in Ihrem Order-Array, dh es ist kein Objekt des Order-Arrays selbst.

Wenn Ihre Aufträge Array auf dem $ Rahmen einer Steuerung definiert ist, dann erstellen Sie das Array auf dem $scope Variable:

$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 

dann auf der Vorlage, Sie <li ng-repeat='p in allParcels'>{{p.upid}}</li>

verwenden können, wenn, aber Sie wollen nicht, dass das Array auf dem $scope zu platzieren, ich glaube, Sie etwas ähnliches wie dies tun können:

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

althoug h Ich bin nicht 100% sicher, dass Angular die .map/.reduce im ng-repeat Ausdruck auswertet (auch ein Array, das auf diese Weise in einem ng-repeat erzeugt wird, ist schlecht beraten, da angular ständig über map/auf jeden $digest Zyklus reduzieren).

+0

Wow. Das ist unglaublich kompliziert. Aber danke für die ausführliche Erklärung, ich hatte keine Ahnung. – Steve

5

Eigentlich die gleiche Antwort von @sylwester. Der bessere Weg, es in filter zu setzen. Und Sie können es wiederverwenden, indem Sie den Parameter propertyName übergeben.

In Ihrem Fall kamen wir 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> 

Hier ist working Fiddle

Verwandte Themen