【问题标题】:Angular ng-repeat with nested json objects?Angular ng-repeat 与嵌套的 json 对象?
【发布时间】:2015-04-01 16:12:25
【问题描述】:

我有一个 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 个包裹)。

【问题讨论】:

    标签: json angularjs angularjs-ng-repeat


    【解决方案1】:

    实际上与@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

    【讨论】:

      【解决方案2】:

      您可以像下面的演示一样创建新的数组“parcels”:

      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>

      【讨论】:

      • 这不适用于外部加载的数据,请参阅plnkr.co/edit/2WnMcwxcmTVA8luquWM9?p=preview,因为那时$scope.data.orders 不存在。我正在通过工厂加载订单。
      • 即使从工厂加载数据,这仍然有效。当数据进入时,您只需要映射新数组。保持范围变量相同,然后在数据进入时将该变量更改为新数组。编辑:这是最好的方法,另一个答案不必要地繁重和/或不起作用。
      • 这很好用!但是,我将如何更改过滤器以访问 JSON 中的 第三 级别?
      • @Bice 你能提供样品 plunkr 吗?
      • 当然:plnkr.co/edit/qY4yoBsGTjl9HsreivAN?p=info 我也在这里作为单独的问题提交了这个问题:stackoverflow.com/questions/33637599/…
      【解决方案3】:

      似乎你只需要一个双嵌套的 for 循环 -

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

      这里的 HTML 可能有点难看,但我不确定你到底想要什么。或者,您可以通过映射创建一个新的 parcels 数组。

      【讨论】:

      • 这个答案会给我 2 个 ul,每个都有 2 个 LI。
      • 我希望用 4 个包裹做一个 UL。
      • @Steve 就像我说的,我不知道你想要输出的具体程度。此外,您始终可以选择映射到新数组。
      • 我编辑了我的问题以使其更清晰。抱歉,如果最初的问题令人困惑。
      • @DavidGrinberg 从技术上讲它不应该存在
      【解决方案4】:

      大量搜索用于动态迭代的漂亮而简单的解决方案。我想出了这个

      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,但绝不会同时显示)将显示该值,如果是对象,则再次循环。

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

      【讨论】:

        【解决方案5】:

        &lt;li ng-repeat="p in orders.parcels"&gt;{{p.upid}}&lt;/li&gt; 无法按您期望的方式工作的原因是因为 parcels 数组是订单数组中每个订单内的一个对象,即它不是订单数组本身的对象。

        如果您的订单数组是在控制器的 $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
        

        然后在模板上,可以使用&lt;li ng-repeat='p in allParcels'&gt;{{p.upid}}&lt;/li&gt;

        但是,如果您不想将数组放在$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 会评估 ng-repeat 表达式中的 .map/.reduce (在 ng-repeat 中以这种方式生成的数组也是不明智的,因为 Angular 必须不断在每个 $digest 循环中通过 map/reduce 生成一个新数组。

        【讨论】:

        • 哇。这非常复杂。不过谢谢你的详细解释,我不知道。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多