1

I have been trying to use an external API to get weather data using $resource, I have been able to get $resource all set up for searching by zipcode, city, and coordinates. When I pass in those values directly from the controller to the service, everything works out the way it should. However, when I use geolocation to get the current coordinates I am getting the correct response back from the API, but for some reason it isn't making it to my html from the controller. I have debugged through this using Chrome Developer Tools for hours now, trying to figure out what is different between directly giving the coordinates (which are the same as the geolocation coordinates) and getting the coordinates from geolocation first. Please help me!

Service:

app.factory('WeatherService',  function($resource) { 
    var apiKey = 'defbe4f40449be22d4a2c7ef18af2a32';
    return {
        Geolocation: $resource('http://api.openweathermap.org/data/2.5/weather?lat=:latitude&lon=:longitude&APPID=:key', {
            latitude: "@latitude", longitude: "@longitude", key: apiKey}, {
            'get' : { method: 'GET', params: {}, format: 'json', isArray: false }}),
        ZipcodeCountry: $resource('http://api.openweathermap.org/data/2.5/weather?zip=:zipCode,:countryCode&APPID=:key', {
            zipCode: "@zipCode" , countryCode: "@countryCode", key: apiKey}, {
            'get' : { method: 'GET', params: {}, format: 'json', isArray: false }}),
        CityCountry: $resource('http://api.openweathermap.org/data/2.5/weather?q=:city,:countryCode&APPID=:key', {
            city: "@city", countryCode: "@countryCode", key: apiKey}, {
        'get' : { method: 'GET', params: {}, format: 'json', isArray: false }})    
    };
});

Logic to map the data received from the API

//Logic for getting API data
var mapWeatherData = function(data) {
    var weather = { name: null, main: {}, wind: {}, clouds: null};
    weather.name = data.name;
    if (data.main) 
    {
        weather.main.current = data.main.temp;
        weather.main.humidity = data.main.humidity;
        weather.main.pressure = data.main.pressure;
        weather.main.min = data.main.temp_min;
        weather.main.max = data.main.temp_max;
    }
    if (data.wind) 
    {
        weather.wind.speed = data.wind.speed;
        weather.wind.deg = data.wind.deg;
    }
    weather.clouds = weather.clouds ? data.clouds.all : undefined;

    return weather;
};

var getWeatherByGeolocation = function(lat, lon, WeatherService) {
    var weather = WeatherService.Geolocation.get({latitude: lat, longitude: lon}, function(data) {
        weather = mapWeatherData(data);
    });
    return weather;
};

Route Config, the weather controller is what is calling the weather service:

app.config(function($routeProvider) {
      $routeProvider.
      when('/home', {
          templateUrl: 'partials/home.html',
          name: "Home",
          controller: function() {
          },
          controllerAs: "homeCtrl",
          css: 'css/partials/home.css'
      }).
      when('/weather', {
          templateUrl: 'partials/weather.html',
          name: "Weather",
          controller: function($scope, $timeout, WeatherService) {'-112.0068800', WeatherService);
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(function(position){
                    $timeout(function(){
                        this.coordinates = {latitude: position.coords.latitude, longitude: position.coords.longitude};
                        this.weather = getWeatherByGeolocation(this.coordinates.latitude, this.coordinates.longitude, WeatherService);
                    });
                });
            }
          },
          controllerAs: "weatherCtrl",
          css: 'css/partials/weather.css'
      }).
      otherwise({
        redirectTo: '/weather'
      });
 });

Replace

if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(function(position){
                    $timeout(function(){
                        this.coordinates = {latitude: position.coords.latitude, longitude: position.coords.longitude};
                        this.weather = getWeatherByGeolocation(this.coordinates.latitude, this.coordinates.longitude, WeatherService);
                    });
                });
            }

With

this.weather = getWeatherByGeolocation('40.3141200', '-112.0068800', WeatherService);

To test giving the coordinates directly to the Service.

I'm still pretty new to AngularJS, so please let me know what I can do to fix this. I have already spent hours and hours researching this, and I'm out of resources. Please and thank you!

UPDATE:

Thanks to Sunil D, they pointed out that I need to assign this to a variable in my controller so that when the service returns with my data, it has something to update because this can change. Here is what I used in my route controller:

controller: function($scope, $timeout, WeatherService) {
            var controller = this;

            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(function(position){
                    $timeout(function(){
                        controller.coordinates = {latitude: position.coords.latitude, longitude: position.coords.longitude};
                        controller.weather = getWeatherByGeolocation(controller.coordinates.latitude, controller.coordinates.longitude, WeatherService);
                    });
                });
            }
            this.weather = controller.weather;
          },
Techgeekster
  • 89
  • 1
  • 13
  • It's b/c of the way the `this` keyword changes its value depending on the context. Inside that callback for `$timeout`, this is not pointing to what you think it's pointing to. If you save a reference to `this` outside of the callback, you can use that reference inside the callback. You see a lot of people doing `var self=this` then using `self` inside the callback. It's a question that is asked a lot :) Most of the answers are [long winded](http://stackoverflow.com/a/3127440/398606), try looking at the "As a function" section of [this one](http://stackoverflow.com/a/134149/398606). – Sunil D. Feb 27 '16 at 17:44
  • Possible duplicate of [How does "this" keyword work within a JavaScript object literal?](http://stackoverflow.com/questions/133973/how-does-this-keyword-work-within-a-javascript-object-literal) – Sunil D. Feb 27 '16 at 17:45
  • Oh my gosh! This worked! You are amazing and I love you! If you put this into an answer, I will mark it as the answer for this question. Thank you so much! – Techgeekster Feb 28 '16 at 06:39

0 Answers0