Angular ng-repeat с вложенными объектами json?
У меня есть объект 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"
}
]
}
]
}
Мне нужно сделать повторитель на уровне второй этого, список "upid" чисел.
Я уже знаю, как получить верхний уровень
<li ng-repeat="o in orders">{{o.ordernum}}</li>
Но я не понимаю, на какой последовательности следует зацикливать уровень вниз. Например, это неверно:
<li ng-repeat="p in orders.parcels">{{p.upid}}</li>
Я также знаю, как вставлять репитеры, чтобы получить это, но в этом случае мне вообще не нужно отображать верхний уровень.
РАЗЪЯСНЕНИЕ
Цель состоит в том, чтобы иметь один список с 4-мя "upid" числами (для каждой посылки есть 2, а в заказе - 2 посылки).
Ответы
Ответ 1
Поиск много для приятного и простого решения для динамического итерации. Я придумал этот
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: укажите шаблон для простой таблицы. первый TD - это ключ, который отображается. другой TD (2 или 3, но никогда не оба) будет показывать значение, если это не объект (число/строка), цикл OR снова, если его объект.
<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>
Ответ 2
Вы можете просто создать новые "парцеллы" массива, как показано ниже:
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>
Ответ 3
На самом деле это тот же ответ @sylwester. Лучший способ разместить его в filter
. И вы можете повторно использовать его, передав параметр propertyName.
В вашем случае мы прошли 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>
Вот рабочий скрипт
Ответ 4
Похоже, вам просто нужен двойной вложенный цикл -
<ul>
<div ng-repeat="o in orders">
<li ng-repeat="p in o.parcels">{{p.upid}}</li>
</div>
</ul>
HTML может быть немного уродливым здесь, но я не уверен, что именно вы собираетесь делать. В качестве альтернативы вы можете просто создать новый массив parcels
через сопоставление.
Ответ 5
Причина, по которой <li ng-repeat="p in orders.parcels">{{p.upid}}</li>
работает не так, как вы ожидаете, состоит в том, что массив парселей является объектом внутри каждого отдельного порядка в вашем массиве заказов, т.е. он не является объектом самого массива заказов.
Если ваш массив заказов определен в области $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
то на шаблоне вы можете использовать <li ng-repeat='p in allParcels'>{{p.upid}}</li>
Если, однако, вы не хотите размещать массив на $scope
, я считаю, что вы можете сделать что-то похожее на это:
<li ng-repeat="p in orders
.map(function (elem) {
return elem.parcels;
})
.reduce(function (previousValue, currentValue) {
return previousValue.concat(currentValue);
})">{{p.upid}}</li>
хотя я не уверен на 100%, что Angular будет оценивать .map/.reduce в выражении ng-repeat
(также имеющий массив, сгенерированный таким образом в ng-repeat
, не рекомендуется, поскольку Angular должен будет постоянно генерировать новый массив через map/reduce в каждом цикле $digest
).