-2

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?

1
  • 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. Commented Apr 16, 2015 at 13:23

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.