Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

i have the following JSON with nested elements

[
    {
        "firstName": "John",
        "lastName": "Smith",
        "gender": "m",
        "places": [{
            "name": "London",
            "contacts": [{
                "type": "phone",
                "value": "123456789"
            },{
                "type": "email",
                "value": "[email protected]"
            }]
        }, {
            "name": "Paris",
            "contact": [{
                "type": "phone",
                "value": "987654321"
            }]
        }]
    },
    {
        "firstName": "Jane",
        "lastName": "Doe",
        "gender": "f",
        "places": [{
            "name": "Paris",
            "contacts": [{
                "type": "email",
                "value": "[email protected]"
            }]
        }]
    }
]

and i'm trying to display it in HTML table with AngularJS and ng-repeat as follows:

Name            Places      Email               Telephone
---------------------------------------------------------
Jonh Smith      London      [email protected]   123456789
                Paris                           987654321
Jane Doe        Paris       [email protected]

Is there a nice way to do it (in one stroke - without too many nested loops) or should I really loop contacts over and over in each "td"-element?

EDIT: I'm looking for an answer like this one here, the only "solution" (if i even can call it that) i came up with is to iterate locations in each "table data"-element over and over, so if each person has 3 locations with 4 phone/emails there will be like 12 iterations per cell or 48 iterations per person (row). Is there really no smart way to do it in ng-repeat or should i just give up with table layout by nested JSON?

share|improve this question

closed as too broad by Ramesh Rajendran, Matthew Green, gunr2171, rene, durron597 Apr 16 '15 at 20:23

There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.If this question can be reworded to fit the rules in the help center, please edit the question.

    
You could do an ng-bind to the td's that you want the values in and give it a function. That function would take the array of data you want to display, pull the data out of it and return it as a string. Keeps your HTML template clean. – Ben Black Apr 16 '15 at 13:23

To give an example based on my comment to your question: use an ng-bind-html on each of the td's and use a function for it that receives the {object}.places array. (In my html I named it person), then in that function get the data you want out of the array and return it as a string

angular.module('app', ['ngSanitize']).controller('testCtrl', ['$scope', function($scope) {
    $scope.persons = [{
      "firstName": "John",
      "lastName": "Smith",
      "gender": "m",
      "places": [{
          "name": "London",
          "contacts": [{
              "type": "phone",
              "value": "123456789"
          },{
              "type": "email",
              "value": "[email protected]"
          }]
        },{
          "name": "Paris",
          "contacts": [{
              "type": "phone",
              "value": "987654321"
          }]
        }]
    },{
      "firstName": "Jane",
      "lastName": "Doe",
      "gender": "f",
      "places": [{
        "name": "Paris",
        "contacts": [{
            "type": "email",
            "value": "[email protected]"
        }]
      }]
    }];
    
    $scope.getPlaces = function(places) {
      var cities = '';
      for (var i = places.length; i-- > 0;) {
        cities += places[i].name + '<br />';
      }
      console.log(cities);
      return cities;
    }

    $scope.getEmails = function(places) {
      var emails = '';
      for (var i = places.length; i-- > 0;) {
        for (var j = places[i].contacts.length; j-- > 0;) {
          if (places[i].contacts[j].type === 'email') {
            emails += places[i].contacts[j].value + '<br />'
          }
        }
      }
      console.log(emails);
      return emails;
    }

    $scope.getPhones = function(places) {
      var phones = '';
      for (var i = places.length; i-- > 0;) {
        for (var j = places[i].contacts.length; j-- > 0;) {
          if (places[i].contacts[j].type === 'phone') {
            phones += places[i].contacts[j].value + '<br />'
          }
        }
      }
      console.log(phones);
      return phones;	
    }    
}]);
td {
  vertical-align: top; 
  border: 1px solid #000;
  min-width: 100px;
}
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular-sanitize.min.js"></script>
  <meta charset="utf-8">
  <title>Test</title>
</head>

<body ng-controller="testCtrl">
  <table>
    <tr>
      <th>Name</th>
      <th>Cities</th>
      <th>Emails</th>
      <th>Phones</th>
    </tr>
    <tr ng-repeat="person in persons">
      <td ng-bind="person.firstName + ' ' + person.lastName">
      <td ng-bind-html="getPlaces(person.places)">
      <td ng-bind-html="getEmails(person.places)">
      <td ng-bind-html="getPhones(person.places)">
    </tr>    
  </table>
</body>

</html>

That should give you a good idea of where to start. Also, note that it requires ngSanitize so make sure you include that if you wind up using this method.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.