Angular ng-repeat with nested json objects?

后端 未结 5 2035
鱼传尺愫
鱼传尺愫 2020-12-30 09:49

I have a JSON object, represented as such:

 {
  \"orders\" : [
    {
      \"ordernum\" : \"PRAAA000000177800601\",
      \"buyer\" : \"Donna Heywood\"
              


        
相关标签:
5条回答
  • 2020-12-30 10:25

    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.

    $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.

    <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 讨论(0)
  • 2020-12-30 10:31

    Seems like you just need a double-nested for loop -

    <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 parcels via mapping.

    0 讨论(0)
  • 2020-12-30 10:33

    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.

    If your orders array is defined on the $scope of a controller, then you create the array on the $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
    

    then on the template, you can use <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:

    <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-repeat expression (also having an array generated this way in an ng-repeat is ill-advised since angular would have to constantly generate a new array via map/reduce on each $digest cycle).

    0 讨论(0)
  • 2020-12-30 10:42

    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>

    0 讨论(0)
  • 2020-12-30 10:49

    Actually its same answer of @sylwester. The better way to put it in filter. And you can reuse it by passing propertyName parameter.

    In your case we passed 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>
    

    Here is working Fiddle

    0 讨论(0)
提交回复
热议问题