Google+

Ok, we’re going to create this today.

 

AngularJS weather Widget

 

And we’re going to achieve this using

  1. AngularJS
  2. Twitter Bootstrap 3
  3. Open Weather Map API
  4. CSS3

Of course we can make similar things using only jQuery but let’s make something cool and learn some stuff on the way.

 

So, a weather widget, huh. Luckily there are APIs where we can get our weather based on location for free. In today’s example we’re going to use http://www.openweathermap.org/API to get the weather data. But there’s a tiny problem (for the basic version of course) to get your location. The API requires you to supply the location of your city, country. We all want our own weather, right ? These are the options we have.

 

  1. Manually supply the location in a text box
  2. Use HTML5 Geo Location API (but it won’t give you city, just lon/lat and then you feed into Google map for GeoCoding)
  3. Use a third party API to get the location.

For our case today, the last option is easier. There are couple of web services where you just send a json call and they give you your location. Like

 

  1. http://ip.pycox.com/json
  2. http://freegeoip.net/

 

I’m going to use a different one – Muslim Prayer times (which i have used in another angularJS post). So it’s http://muslimsalat.com/daily.json

 

So the app flow will be

 

 

Now, let’s get into coding business. As a Disclaimer, i want to mention that this part of the project didn’t use all the standards – which we’ll do in another post using Grunt and all that.

 

So we have this one file which has controller, services and router.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
var App = angular.module("weatherApp", ['ngRoute', 'ngAnimate', 'weatherControllers', 'weatherServices']);

App.config(['$routeProvider', '$locationProvider',
  function($routeProvider, $locationProvider) {
    $routeProvider.when('/', {
      templateUrl: 'js/views/weather.html',
      controller: 'GetWeatherCtrl'
    });
  }
])


var weatherControllers = angular.module("weatherControllers", []);
weatherControllers.controller("AppController", ['$route', '$routeParams', '$location',
  function($route, $routeParams, $location) {

  }
]);

weatherControllers.controller("GetWeatherCtrl", ['$scope', 'weatherApi',
  function($scope, weatherApi) {
    $scope.currentTime = moment().format('h:mm a');
    weatherApi.getLocation().then(function(res) {            
      weatherApi.getWeeklyWeather(res.data.city+","+res.data.country_code).then(function(response) {
        $scope.data = response.data;
        if ($scope.data.list.length) {
          $scope.data.list.forEach(function(i, v) {
            var date = moment(i.dt * 1000);
            i.dt = {
              day: date.format("ddd")
            };
            if (moment().format("d") == date.format("d")) {
              i.dt.today = true;
            }
          });
        }
      });
    });
  }
]);

var weatherServices = angular.module('weatherServices', []);

weatherServices.factory('weatherApi', ['myHttp',
  function(myHttp) {
    return {
      getLocation: function() {
        return myHttp.jsonp("http://muslimsalat.com/daily.json?callback=JSON_CALLBACK");
      },
      getWeeklyWeather: function(city) {        
        return myHttp.get('http://api.openweathermap.org/data/2.5/forecast/daily?q='+city+'&mode=json&units=metric');
      }
    }
  }
]);


weatherServices.factory('myHttp', ['$http', 'myCache',
  function($http, myCache) {

    var headers = {
      'cache': myCache,
      'dataType': 'json'
    };
    var APPID = "bc1e24c531732375aece237bb2a5d49a";
    return {
      config: headers,
      get: function(url, success, fail) {
        return $http.get(url + "&APPID=" + APPID, this.config);
      },
      getLocal: function(url, success, fail) {
        return $http.get(url);
      },
      jsonp: function(url, success, fail) {
        return $http.jsonp(url, this.config);
      }
    };
  }
]);

weatherServices.factory('myCache', function($cacheFactory) {
  return $cacheFactory('myCache', {
    capacity: 100
  });
});

function JSON_CALLBACK(){
  // Nothing
}

So we have one controller named GetWeatherCtrl, One Service weatherServices for API calls and a custom http wrapper so that we can change from http to resource or some other method if we want. As you can see in the top part the App is configured with dependencies and a single route, since we don’t have any other pages.

 

And there we have a service called weatherApi where we call the API to return the json and it will return the promise by the custom http wrapper we’re using. It’s in the very basic now. For authenticated API services, it becomes handy when you have to send some credentials with all requests.

 

In the controller if you notice, we have put the weather call after the geo location resolution. So the weather API will wait for being called for the geolocation to be resolved. The muslimsalat.com’s API availability is quite high and without limits. So it gives accurate result most of the times.

 

In the view, we have use a bootstrap structure. weather.html partial has all the necessary codes where we have separated today and rest of the days. So there are two columns grid

 

Btw, we used the awesome library for date calculation/formatting moment.js – for easy time/date formating. Who cares 5.5kb these days anyway ?

 

That’s pretty much it. Next we’ll do some more awesome things with this widget

 

  1. Add Google map to choose any location for weather
  2. Add multi series D3 charts for weekly weather presentation
  3. Add tooltips for more information on days
  4. Add icons based on weather conditions

 

So keep checking us

 


Post Meta

Comment(s):
0
Posted on:
March 30, 2014
Category:
AngularJS, blog, Web development
Tags:
, , ,