Pregunta

I have an Angular app communicating with an external API. I'm able to generate the initial view from an Angular $resource call. My problem is that I have a form that runs a function on ng-click. That function then queries the API again and is supposed to update that same scoped variable but I'm not able to get the results of the second $resource call to update the scoped variable.

In my controller, this is the initial call that gets the data that shows up in the view initially:

// Initial weather and geolocation data var Weather = $resource('http://example.com/:method'); Weather.get({method: 'current'}).$promise.then(function(weather) { // Success $scope.weather = weather.weather; $scope.geolocation = weather.location; }, function(error) { // Failure $scope.weather = error; });

So far so good, the view updates and I can show the JSON that the API sends back with {{ weather.currently.temp }} as well as all the data in the {{ geolocation }} variable.

However, I have a form (it is properly set up to talk to the controller) that upon submission should make another request to the same API and return new data:

// Search functionality $scope.weatherLookup = function(query) { $http.get('http://example.com/location/' + query).then(function (value) { $scope.weather = value; }); };

At this point, in the view, the {{ weather }} variable does not update anywhere. At all. If I throw a console.log function inside the weatherLookup function I get undefined when trying to get the value of $scope.weather but I do get a valid JSON object when I ask for value in that same console.log() statement instead.

How can I get that value variable assigned to the $scope.weather inside $scope.weatherLookup so that it can update that value and have it bubble up to the view?

¿Fue útil?

Solución

This is the solution I found - I welcome alternative/better ways to do this.

Apparently $scope.weather references multiple values. That is to say, because the $resource and $http methods return promises and the nature of those promises, $scope.weather can actually reference two separate objects as far as the view and controller are concerned. The way I solved the problem was by using $rootScope to make sure the same weather object was always overwritten.

Here's the new code:

'use strict';

angular.module('myApp')
  .controller('WeatherCtrl', function ($scope, Restangular, $rootScope) {

    // Get initial weather data (NOW WITH $rootScope)
    Restangular.one('current').get().then(function(weather) {
      $rootScope.weather = weather.weather;
      $scope.geolocation = weather.location;
    });

    // Search functionality
    $scope.weatherLookup = function(query) {
      Restangular.one('location/' + query).get().then(function(newWeather) {
        $rootScope.weather = newWeather;
        console.log($rootScope.weather);
      });
      console.log($rootScope.weather);
    };

  });

I switched from using Angular's own $resource and $http services to the wonderful Restangular library. Despite this change, the original problem persisted until I used $rootScope. I tested this theory using $resource and $http and it still worked so I know that the issue was that $scope.weather was somehow splitting off and referencing two separate objects under the hood because of the way $scope and promises work in Angular.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top