Frnnd Sgz
Frnnd Sgz

Reputation: 328

Call function inside ng-repeat to retrieve value

I'm having this situation I'm iterating over a json response from an endpoint:

chunk of controller code:

$http({
    method: 'GET',
    url: 'http://mywebsite.com/api/v1/stores/'
}).
success(function(data, status, headers, config) {
    $scope.stores = data;
}).
error(function(data, status, headers, config) {
    $scope.name = 'Error!';
});

and on my html view side I've got this:

<tbody>
    <tr ng-repeat="store in stores">
        <td>{{store.name}}</td>
        <td> {{store.type}} </td>
        <td><span ng-repeat="client in retrieveClientName(store.client_id)">
                {{client.name}}
            </span>
        </td>
        <td>{{store.address}}</td>
    </tr>
</tbody>

As you can see I'm trying to retrieve the client name using a function that receives an store.client_id from the values inside the stores array. Normally using a function triggered by a ng-click will be easy but how can I achieve this "on the fly" while I'm iterating?. Because executing this I get a kind of infinite loop that breaks all apart.

here is the code of the function that returns client name on the controller side:

$scope.retrieveClientName = function(id) {
   $http({
          method: 'GET',
          url: 'http://mywebsite.com/api/v1/clients?client_id='+id
      }).
      success(function(data, status, headers, config) {
          return $scope.clients=data;
      }).
      error(function(data, status, headers, config) {
          $scope.name = 'Error!';
      });
    }

I have also try using mg-init directive

<td  ng-init="clients=retrieveClientName(store.client_id)"><span ng-repeat="client in clients">{{client.name}}</span></td>

Upvotes: 0

Views: 4126

Answers (3)

Icycool
Icycool

Reputation: 7179

One way would be get all data when you get the stores back

$http({
    method: 'GET',
    url: 'http://mywebsite.com/api/v1/stores/'
}).
success(function(data, status, headers, config) {
    $scope.stores = data;
    angular.forEach($scope.stores, function(store){
        $scope.retrieveClientName(store.client_id).then(function(clients){
             store.clients = clients;
        });
    });
}).
error(function(data, status, headers, config) {
    $scope.name = 'Error!';
});

Edit: I would change the structure a bit for cleaner code

$scope.retrieveClientName = function(store) { // pass in store so we can attach results here
   $http({
      method: 'GET',
      url: 'http://mywebsite.com/api/v1/clients?client_id='+store.client_id
   }).
   success(function(data, status, headers, config) {
      return store.clients = data; // attach result in object
   }).
   error(function(data, status, headers, config) {
      $scope.name = 'Error!';
   });
}

$http({
    method: 'GET',
    url: 'http://mywebsite.com/api/v1/stores/'
}).
success(function(data, status, headers, config) {
    $scope.stores = data;
    angular.forEach($scope.stores, function(store){
        $scope.retrieveClientName(store); // no need .then here
    });
}).
error(function(data, status, headers, config) {
    $scope.name = 'Error!';
});

<tbody>
    <tr ng-repeat="store in stores">
        <td>{{store.name}}</td>
        <td> {{store.type}} </td>
        <td><span ng-repeat="client in store.clients"> <!-- use data here -->
                {{client.name}}
            </span>
        </td>
        <td>{{store.address}}</td>
    </tr>
</tbody

Upvotes: 1

fantarama
fantarama

Reputation: 880

The retrieveClientName function is wrong: the $http return a promise, the return value of success callback is not the return value of the function and you can't bind the ng-repeat to a promise, try this one:

$scope.retrieveClientName = function(id) {
    return $resource('http://mywebsite.com/api/v1/clients?client_id='+id).query();
}

Don't forget to include the ngResource dependency.

Upvotes: 1

Maciej Sikora
Maciej Sikora

Reputation: 20132

You must understand that $http jest asynchronous, so Your response will be back after all ng-repeat, so such thing must be done in controller in $q.all and after that render view with ng-repeat.

So do foreach on stores and in foreach add to array, next use this array in $q.all, after $q.all render view.

Upvotes: 1

Related Questions