2015-02-02 29 views
10

У меня есть JSON объект, представленный как таковой:Угловой ng-повтор с вложенными объектами json?

{ 
    "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" 
     } 
     ] 
    } 
    ] 
} 

мне нужно сделать повторитель на второго уровня этого, в списке «upid» чисел.

Я уже знаю, как получить верхний уровень

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

Но я неясными на последовательности в цикле уровень вниз. Например, это неправильно:

Я также знаю, как гнездо ретрансляторы, чтобы получить это, но в этом случае мне не нужно, чтобы отобразить верхний уровень на всех.

РАЗЪЯСНЕНИЕ

Цель здесь иметь один список с 4 «upid» номера (есть 2 для каждого участка, и есть 2 посылки в порядке).

ответ

0

Ищите много для приятного и простого решения для динамического итерации. Я придумал это

JAVASCRIPT (угловой): человек является примером вложенного объекта. функция 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> 
4

Похоже, вы просто нужно дважды вложенная цикл -

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

HTML, может быть немного некрасиво, но я не уверен, что именно вы собираетесь. В качестве альтернативы вы можете просто создать новый массив из parcels через сопоставление.

+0

Этот ответ даст мне 2 uls, каждый из которых имеет 2 LI. – Steve

+0

Я ищу сделать один UL с 4 посылками. – Steve

+0

@Steve Как я уже сказал, я не знаю, как конкретно вы хотите выход. Кроме того, у вас всегда есть варианты сопоставления с новым массивом. –

5

Вы можете просто создать новый массив «посылок», как в демо ниже:

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

Это не работает с данными, загружаемыми извне, см. Http://plnkr.co/edit/2WnMcwxcmTVA8luquWM9? p = preview поскольку '$ scope.data.orders' не существует. Я заказываю заказы через завод. – Steve

+0

Это будет работать даже при загрузке данных с завода. Вам просто нужно будет сопоставить новый массив при вводе данных. Сохраняйте переменную с областью действия одинаково, а затем просто изменяйте эту переменную на новый массив, когда данные поступают. Редактировать: это лучший способ сделать это, другие ответы излишне тяжелы и/или не будут работать. – ribsies

+0

@Steve см. Здесь http://plnkr.co/edit/FXpgRDqQTAm6QUstI86z?p=preview – sylwester

0

Причина, по которой не работает так, как вы ожидаете, потому что массив посылок является объектом внутри каждого индивидуального порядка в вашем массиве заказов, т. е. он не является объектом самого массива заказов.

Если ваш заказ массив определяется на $ рамки контроллера, то вы создаете массив по переменной $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> 

Althoug h Я не уверен на 100%, что Angular будет оценивать значение .map/.reduce в выражении ng-repeat (также имеющее массив, сгенерированный таким образом в ng-repeat, не рекомендуется, так как угловое значение должно постоянно генерировать новый массив через map/уменьшить каждый цикл $digest).

+0

Wow. Это невероятно сложно. Но спасибо за подробное объяснение, я понятия не имел. – Steve

5

Фактически его же ответ @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> 

Вот working Fiddle

Смежные вопросы