Reputation: 187
This is a basic weather app that grabs info from an open weather API. Upon loading, it gets the weather information for the default city and I'm able to successfully log the returned info to the console, however my view doesn't update until I switch to a different view and then back. I feel like a $scope.$apply needs to go somewhere, but I couldn't get it working anywhere I tried.
App:
var weather = angular.module('weather', ['ngRoute', 'ngResource', 'ui.router']);
weather.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/overview');
$stateProvider
.state('overview', {
url: '/overview',
templateUrl: 'pages/overview.html',
controller: 'overviewController'
})
.state('forecast', {
url: '/forecast',
templateUrl: 'pages/forecast.html'
})
.state('details', {
url: '/details',
templateUrl: 'pages/details.html'
})
});
weather.controller('homeController', ['$scope', '$location', '$resource', 'weatherService', function($scope, $location, $resource, weatherService) {
$scope.txtCity = weatherService.city;
$scope.submit = function() {
weatherService.city = $scope.txtCity;
weatherService.getForecast(weatherService.city, function(x){
weatherService.currentForecast = x;
// TESTING
console.log(x);
});
};
// Run the submit function initially to retrieve weather data for the default city
$scope.submit();
// Function to determine the active tab, sets its class as "active"
$scope.isActive = function (path) {
return ($location.path().substr(0, path.length) === path) ? 'active' : '';
}
}]);
weather.controller('overviewController', ['$scope', '$filter', 'weatherService', function($scope, $filter, weatherService) {
$scope.currentForecast = weatherService.currentForecast;
// Kelvin to Fahrenheit
$scope.convertTemp = function(temp) {
return Math.round((1.8*(temp - 273))+32);
}
$scope.convertToDate = function(dt) {
var date = new Date(dt * 1000);
return ($filter('date')(date, 'EEEE, MMM d, y'));
};
}]);
weather.service('weatherService', function($resource, $http){
this.currentForecast = null;
// default city
this.city = 'Chicago, IL';
this.getForecast = function(location, successcb) {
$http({
method : "GET",
url : "http://api.openweathermap.org/data/2.5/forecast/daily?q="+location+"&mode=json&cnt=7&appid=e92f550a676a12835520519a5a2aef4b"
}).success(function(data){
successcb(data);
}).error(function(){
});
}
});
overview.html (view):
<h4>Daily</h4>
<ul>
<li ng-repeat="w in currentForecast.list">{{ convertToDate(w.dt) }} {{ convertTemp(w.temp.day) }}°</li>
</ul>
Submit form:
<form ng-submit="submit()">
<button type="submit" class="btn btn-primary btn-sm">Get Forecast</button>
<input type="text" ng-model="txtCity">
</form>
Upvotes: 1
Views: 51
Reputation: 12025
Change your service function to:
this.getForecast = = function(location) {
return $http({
method : "GET",
url : "http://api.openweathermap.org/data/2.5/forecast/daily?q="+location+"&mode=json&cnt=7&appid=e92f550a676a12835520519a5a2aef4b"
}).then(
function(response) {
return response.data;
}
)
};
And in your controller, use it like this in the submit
function:
weatherService.getForecast(weatherService.city).then(
function(data) {
weatherService.currentForecast = data;
console.log(data);
}
);
This allows you to handle the success function of the $http
promise directly from the controller. Currently you're passing the function to the service, and it doesn't know what the weatherService
parameter is, because it outside of the service scope (It's avalable in the controller).
Now, in your overviewController
controller, you can watch for changes inside the service like this:
$scope.$watch(function() { return weatherService.currentForecast; },
function(newVal) {
if(!newVal) return;
$scope.currentForecast = newVal;
}, true);
Upvotes: 3