Maarten Meeusen
Maarten Meeusen

Reputation: 482

Display function result in ng-repeat

I am working on a little angular project and am stuck. I am filling a table with runs from a rest call with ng-repeat. In every run there are gps coordinates. I have a function that gives back the city where these coordinates are. What I want is that the run shows the city instead of the coordinates. So when the repeat fills the table it should call this function for each run and show the return value of the function, which is the city.

Right now I have a button that calls the function and then it gets shown but I want the result to be shown on load. Can anybody help me?

Here's what I have so far:

$http.get('/fastrada/getRun.do').success(function (data) {
        $scope.runs = data;

        angular.forEach($scope.runs, function (run){
            /*run.city =*/ $scope.getInfo(run);
        });

        $scope.loading=true;
    });

$scope.getInfo = function(run)
        {
            var latlng =  run.latitude+","+run.longitude;
            var request = new XMLHttpRequest();

            if(run.latitude != 0 && run.longitude != 0) {
                request.open('GET', 'http://maps.googleapis.com/maps/api/geocode/json?latlng=' + latlng, true);

                request.onload = function () {
                    if (request.status == 200 || request.status == 0) {
                        // Success!
                        var data = JSON.parse(request.responseText);

                        if(data !== undefined && data.results[0] !== undefined){
                            run.city = data.results[0].address_components[2].long_name;
                        }else {
                            run.city = "undefined";
                        }
                        //return data.results[0].address_components[2].long_name;
                    }
                    else {
                        // We reached our target server, but it returned an error
                        //alr.textContent = "Google Server Request didn't worked";
                    }
                };

                request.onerror = function () {
                    // There was a connection error of some sort
                    //alr.textContent = "Google Server Request didn't worked";
                };

                request.send();
            }else{
                run.city = "undefined";
            }
        }

And the html:

<tr ng-repeat="run in runs track by $index">
                                    <td>{{run.city}}</a></td>
                                    <td>{{run.getTime}}</td>
                                    <td><button ng-click="getInfo(run)">Get City</button></td>
                                </tr>

Here is a Plunk demonstrating what I mean. Thanks!

Upvotes: 0

Views: 195

Answers (1)

Michael Oryl
Michael Oryl

Reputation: 21642

You could do this using a separate controller for each Run in the ng-repeat and then triggering the lookup in that RunController instance instead of using a button and a getInfo() method in the parent controller.

I've modified your Plunk to make it work. Here it is.

This is the new RunController:

fastradaApp.controller('RunController', ['$scope', '$http', '$log',
  function($scope, $http, $log) {
    $scope.loading = false;
    $scope.getInfo = function() {  // note we reference $scope.run (as created by the ng-repeat loop)
      console.log($scope.run);
      if ($scope.run !== undefined) {
        var latlng = $scope.run.latitude + "," + $scope.run.longitude;
        if ($scope.run.latitude !== 0 && $scope.run.longitude !== 0) {
          $http.get('http://maps.googleapis.com/maps/api/geocode/json?latlng=' + latlng)
            .success(function(data, status, headers, config) {
              $log.info(data);

              if (data !== undefined && data.results[0] !== undefined) {
                $scope.run.city = data.results[0].address_components[2].long_name;
              } else {
                $scope.run.city = "undefined";
              }
            })
            .error(function(data, status, headers, config) {
              // called asynchronously if an error occurs
              $scope.run.city = "undefined";
            });
        } else {
          $scope.run.city = "undefined";
        }
      }

    };
    $scope.getInfo();
  }
]);

Notice that there's no "run" parameter passed to the getInfo() function. Instead it makes use of $scope.run, which is the particular run instance created by the ng-repeat loop.

Also note that I replaced your complex request code with a straightforward $http call. It's much cleaner since it requires no real setup and you don't even have to use JSON.parse() on the results.

I've also put in some logging using the $log service just to make it more obvious. It's not needed to work, of course.

The HTML remains the same:

<tr ng-repeat="run in runs" ng-controller="RunController">
    <td>{{run.runId}}</td>
    <td>{{run.city}}</td>
    <td>{{run.time}}</td>
</tr>

Upvotes: 1

Related Questions