带有嵌套json对象的Angular ng-repeat?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28282419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular ng-repeat with nested json objects?
提问by Steve
I have a JSON object, represented as such:
我有一个 JSON 对象,表示如下:
{
"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"
}
]
}
]
}
I need to do a repeater on the secondlevel of this, a list of the "upid" numbers.
我需要在第二层做一个中继器,一个“upid”数字列表。
I know already how to get the top level
我已经知道如何获得顶级
<li ng-repeat="o in orders">{{o.ordernum}}</li>
<li ng-repeat="o in orders">{{o.ordernum}}</li>
But I am unclear on the sequence to loop a level down. For example, this is wrong:
但我不清楚循环一个级别的顺序。例如,这是错误的:
<li ng-repeat="p in orders.parcels">{{p.upid}}</li>
<li ng-repeat="p in orders.parcels">{{p.upid}}</li>
I also know how to nestrepeaters to get this, but in this case i don't need to display the top level at all.
我也知道如何嵌套中继器来获得它,但在这种情况下,我根本不需要显示顶级。
CLARIFICATION
澄清
The goal here is to have one list with the 4 "upid" numbers (there are 2 for each parcel, and there are 2 parcels in the order).
这里的目标是有一个包含 4 个“upid”数字的列表(每个包裹有 2 个,并且订单中有 2 个包裹)。
采纳答案by chenchuk
Searching a lot for nice and simple solution for iterating dynamically. I came up with this
搜索了很多用于动态迭代的漂亮而简单的解决方案。我想出了这个
JAVASCRIPT (angular): a person is an example of nested object. the is_object function will be use in the HTML view.
JAVASCRIPT(angular):一个人是嵌套对象的一个例子。is_object 函数将在 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: define a template for simple table. the 1st TD is the key which is displayed. another TD (2 or 3, but never both) will be show the value if its not an object (number / string), OR loop again if its an object.
HTML:定义简单表格的模板。第一个 TD 是显示的键。如果不是对象(数字/字符串),则另一个 TD(2 或 3,但永远不会同时显示)将显示该值,如果它是对象,则再次循环或循环。
<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>
回答by sylwester
You can just create new array 'parcels' like in demo below:
您可以像下面的演示一样创建新的数组“包裹”:
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>
回答by Pankaj Parkar
Actually its same answer of @sylwester. The better way to put it in filter. And you can reuse it by passing propertyName parameter.
实际上它与@sylwester 的答案相同。将它放入filter. 您可以通过传递 propertyName 参数来重用它。
In your case we passed parcels
在你的情况下,我们通过了 parcels
JS
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
HTML
<ul>
<li ng-repeat="o in ordersList.orders | createarray: 'parcels'">{{o.upid}}</li>
</ul>
Here is working Fiddle
这是工作小提琴
回答by David says Reinstate Monica
Seems like you just need a double-nested for loop -
好像你只需要一个双嵌套的 for 循环 -
<ul>
<div ng-repeat="o in orders">
<li ng-repeat="p in o.parcels">{{p.upid}}</li>
</div>
</ul>
The HTML might be a little ugly here, but I'm not sure what exactly you are going for. Alternatively you could just create a new array of the parcelsvia mapping.
这里的 HTML 可能有点难看,但我不确定您到底要做什么。或者,您可以创建一个新的parcels通孔映射数组。
回答by Brian Law
The reason that <li ng-repeat="p in orders.parcels">{{p.upid}}</li>does not work the way you expect is because the parcels array is an object inside each individual order in your order array, i.e. it is not an object of the orders array itself.
<li ng-repeat="p in orders.parcels">{{p.upid}}</li>无法按您期望的方式工作的原因是,parcels 数组是订单数组中每个单独订单内的对象,即它不是订单数组本身的对象。
If your orders array is defined on the $scope of a controller, then you create the array on the $scopevariable:
如果您的订单数组是在控制器的 $scope 上定义的,那么您将在$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
then on the template, you can use <li ng-repeat='p in allParcels'>{{p.upid}}</li>
然后在模板上,您可以使用 <li ng-repeat='p in allParcels'>{{p.upid}}</li>
If, however, you do not want to place the array on the $scope, I believe you can do something similar to this:
但是,如果您不想将数组放在 上$scope,我相信您可以执行以下操作:
<li ng-repeat="p in orders
.map(function (elem) {
return elem.parcels;
})
.reduce(function (previousValue, currentValue) {
return previousValue.concat(currentValue);
})">{{p.upid}}</li>
although I'm not 100% sure that Angular will evaluate the .map/.reduce in the ng-repeatexpression (also having an array generated this way in an ng-repeatis ill-advised since angular would have to constantly generate a new array via map/reduce on each $digestcycle).
虽然我不是 100% 确定 Angular 会评估ng-repeat表达式中的 .map/.reduce (也有一个以这种方式生成的数组ng-repeat是不明智的,因为 angular 必须不断地通过 map/reduce 生成一个新数组每个$digest循环)。

