0

I'm having trouble understanding the source of an error, since html side picks up things like list[3].main.temp just fine, but in the second for loop of generateList function i get error right on the $scope.list[i].main.temp which says

TypeError: Cannot read property '0' of undefined =\

The code is supposed to take a list of 30 cities, pick random 10 and display their current temperature.

var WeatherApp = angular.module("WeatherApp", ["ngRoute", "ngResource"]).
config(function ($routeProvider) {
    $routeProvider.
        when('/', { controller: ListCtrl, templateUrl: 'list.html' }).
        otherwise({ redirectTo: '/' });
});

WeatherApp.factory('City', function ($resource) {
return $resource('/api/City/:id', { id: '@id' }, {update: { method: 'PUT'}});
 });

var ListCtrl = function ($scope, $location, City, $http) {
$scope.city = City.query();

$scope.units = 'metric';
$scope.appId = '';
$scope.displayNum = 10;
$scope.display = [];
$scope.display.temp = [];

$scope.generateList = function () {
    $scope.exp = City.query(function (exp) {
        shuffle(exp);
        $scope.cityIdAr = [];
        for (var i = 0; i < $scope.displayNum; ++i) {
            $scope.display.push($scope.exp[i]);
            $scope.cityIdAr.push($scope.exp[i].CityId);
        };
        $scope.cityId = $scope.cityIdAr.join();
        $scope.getWeather();
        for (var i = 0; i < $scope.displayNum; ++i) {
            $scope.display.temp.push($scope.list[i].main.temp);
        };
    });
};

function shuffle(ob) {
    for (var j, x, i = ob.length; i; j = Math.floor(Math.random() * i), x = ob[--i], ob[i] = ob[j], ob[j] = x);
    return ob;
};

$scope.getWeather = function () {
    var url = 'http://api.openweathermap.org/data/2.5/group';
    $http.jsonp(url, {
        params: {
            id: $scope.cityId,
            APPID: $scope.appId,
            units: $scope.units,
            callback : 'JSON_CALLBACK'
        }
    }).success(function (data, status, headers, config) {
        $scope.data = data;
        $scope.list = data.list;
        });
};


$scope.generateList();
};
Comintern
  • 21,855
  • 5
  • 33
  • 80
  • [How to return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Andreas Jun 20 '15 at 13:36

2 Answers2

0

The problem may be that $scope.list is undefined until the callback is ran. You could return a promise from $scope.getWeather and resolve it in $scope.generateList, then execute the for loop when the data is retrieved (inside the callback) e.g.

Return a promise from $scope.getWeather:

$scope.getWeather = function () {
  ...
  return $http.jsonp(...)
}

and then in $scope.generateList:

...
$scope.getWeather().success(function(data, status, headers, config) {
  $scope.data = data;
  $scope.list = data.list;
  for (var i = 0; i < $scope.displayNum; ++i) {
    $scope.display.temp.push($scope.list[i].main.temp);
  };
}

or something along these lines.

chris
  • 1,787
  • 1
  • 13
  • 13
  • still learning that stuff guess i need to turn my gaze to promise :) – Grigoriy Oprichnikov Jun 20 '15 at 14:15
  • Glad I could help. Working with promises is fairly straight forward. You'll get the hang of it in no time. The important part is keeping your controllers thin. Try and make use of services for data retrieval. – chris Jun 20 '15 at 14:31
0

$scope.display is a List use another variable

var WeatherApp = angular.module("WeatherApp", ["ngRoute", "ngResource"]).
config(function ($routeProvider) {
    $routeProvider.
        when('/', { controller: ListCtrl, templateUrl: 'list.html' }).
        otherwise({ redirectTo: '/' });
});

WeatherApp.factory('City', function ($resource) {
return $resource('/api/City/:id', { id: '@id' }, {update: { method: 'PUT'}});
 });

var ListCtrl = function ($scope, $location, City, $http) {
$scope.city = City.query();

$scope.units = 'metric';
$scope.appId = '';
$scope.displayNum = 10;
$scope.display = [];
$scope.temp = [];

$scope.generateList = function () {
    $scope.exp = City.query(function (exp) {
        shuffle(exp);
        $scope.cityIdAr = [];
        for (var i = 0; i < $scope.displayNum; ++i) {
            $scope.display.push($scope.exp[i]);
            $scope.cityIdAr.push($scope.exp[i].CityId);
        };
        $scope.cityId = $scope.cityIdAr.join();
        $scope.getWeather();
        for (var i = 0; i < $scope.displayNum; ++i) {
            $scope.temp.push($scope.list[i].main.temp);
        };
    });
};

function shuffle(ob) {
    for (var j, x, i = ob.length; i; j = Math.floor(Math.random() * i), x = ob[--i], ob[i] = ob[j], ob[j] = x);
    return ob;
};

$scope.getWeather = function () {
    var url = 'http://api.openweathermap.org/data/2.5/group';
    $http.jsonp(url, {
        params: {
            id: $scope.cityId,
            APPID: $scope.appId,
            units: $scope.units,
            callback : 'JSON_CALLBACK'
        }
    }).success(function (data, status, headers, config) {
        $scope.data = data;
        $scope.list = data.list;
        });
};


$scope.generateList();
};

enter image description here

Shubham Nigam
  • 3,844
  • 19
  • 32