Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have multiple JSON files:

main.json:

{
  "MainRegister": [
    {
      "name": "Name1",
      "url": "url1.json",
    },
    {
      "name": "Name2",
      "url": "url2.json",
    },
 ]
}

url1.json

{
  "SubInformation": {
    "description": "Hello World 1",
    "identifier": "id1",
  }
}

url2.json

{
  "SubInformation": {
    "description": "Hello World 2",
    "identifier": "id2",
  }
}

Now I want to create a ng-repeat div in my index.html such that it loads all the fields from the files, moreover I want to display the following output:

  • Name1: Hello World 1 (id1)
  • Name2: Hello World 2 (id2)

How can I bind these files in a ng-repeat way? Or is there another way?

share|improve this question

3 Answers 3

up vote 1 down vote accepted

You need to load them first, then set up a scope variable that contains the necessary data in an array. You can do the $http get in your controller (as in the example below), but if it is anything reusable or more than a simple app, I would recommend doing it in an injected service.

.controller('MyCtrl', function($scope,$http){
   $scope.entries = [];
   $http.get('main.json').success(function(data) {
      angular.forEach(data.MainRegister,function(entry) {
         $http.get(entry.url).
          success(function(data) {
            $scope.entries.push(angular.extend(entry,data.SubInformation);
         });
      });
   });
});

and then your template can look something like

<div ng-repeat="entry in entries">
  <span>{{entry.name}}: {{entry.description}} ({{entry.id}})</span>
</div>

You can use filters if you want to order them, or load the $scope.entries in a particular order, or if you don't want to show any entries until all are ready, then you can set a ready var, or only set $scope.entries at the end, etc.

Let me add that I don't like that kind of deeper and deeper embedded ajax calls, as well as the series of them, but it is a question of style. I have become a big fan of caolan's async library for making the above controller code far cleaner. http://github.com/caolan/async

share|improve this answer
    
Also, what do you mean with an injected service. How would that work? –  JohnAndrews Nov 28 '14 at 13:05
    
Thanks for the update. I noticed that doing so, only the data in the sub-JSON files are accessible. How do I keep the original? Thanks –  JohnAndrews Nov 28 '14 at 13:20
    
On my previous question: I have done an edit (needs to be review). Basically replace to the following: $scope.entries.push(angular.extend(entry,data.SubInformation); –  JohnAndrews Nov 28 '14 at 13:28
    
Yeah, you could do it that way. As long as it is an object with the right properties in the end. –  deitch Nov 29 '14 at 16:09
    
Not only does this code not work for me, but it screws up my code for custom interpolateprovider –  edmund_spenser Dec 1 '14 at 3:36

The Simple Way:

Analog to UNION statement of SQL ANSI.

For more information, see the example of https://docs.angularjs.org/api/ng/directive/ngInit

<script>
  angular.module('initExample', [])
    .controller('ExampleController', ['$scope', function($scope) {
      $scope.list = [['a', 'b'], ['c', 'd']];
    }]);
</script>
<div ng-controller="ExampleController">
  <div ng-repeat="innerList in list" ng-init="outerIndex = $index">
    <div ng-repeat="value in innerList" ng-init="innerIndex = $index">
       <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
    </div>
  </div>
</div>

Result:

list[ 0 ][ 0 ] = a;
list[ 0 ][ 1 ] = b;
list[ 1 ][ 0 ] = c;
list[ 1 ][ 1 ] = d;
share|improve this answer

Something like this

HTML

<body ng-app="app">
  <div ng-controller="mainController">
    <ul ng-repeat="item in items">
      <li>{{item.name}} : {{item.description}} ({{item.identifier}})</li>
    </ul>
  </div>
</body>

Code

var app = angular.module("app", []);

var mainController = function($scope, $http) {
  $scope.items = [];
  $scope.dynamicKeys = [];

  $http.get('main.json').success(function(response) {
    var mainData = response.MainRegister,
      url, name, description, identifier;


    mainData.forEach(function(entry, index) {
      if (index == 0) {
        for (var key in entry) {

          $scope.dynamicKeys.push({
            nameKey: key
          });
        }
      }

      name = entry.name;
      url = entry.url;

      $http.get(url).success(function(urlResponse) {
        description = urlResponse.SubInformation.description;
        identifier = urlResponse.SubInformation.identifier;

        var element ={};
        $scope.dynamicKeys.forEach(function (key) {
          element[key.nameKey] = entry[key.nameKey];
        });
        element.description = description;
        element.identifier = identifier;

        $scope.items.push(element);
      });

    });
  });
}

app.controller("mainController", ["$scope", "$http", mainController]);

Look plunker

share|improve this answer
    
Thank you for the answer Semin. Only the second part looks to me too manual... what if the JSON file changes? Like you are using specific names. See the other answer, that one suits me better. Nevertheless, thank you. –  JohnAndrews Nov 28 '14 at 13:29
    
>>what if the JSON file changes - show example please –  Igor Semin Nov 28 '14 at 13:45
    
lets say that in the json file the field .name changes to .name2, then this is not taken into account. Or when additional fields arrive in the json field like, .status, then this needs to be manually added to the code in $scope.items.push. I am not an expert, perhaps you have another view on it? –  JohnAndrews Nov 28 '14 at 13:47
1  
use dynamic initializator plnkr.co/edit/Ljd9ZLqW9ExIp5u2SWqc?p=preview. I update my plunker and answer –  Igor Semin Nov 28 '14 at 15:15

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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