Creating Weather & Time widget web part using Angular – SharePoint 2013

Sharepoint Weather with angularjs

Continuation with previous post Creating Calendar Agenda type widget will create a Weather & time widget.

The output will look like:

weather

Desktop view of Weather and Date

weather2

Mobile view of Weather and Date

Features:

  • Drop down with different locations to choose from
  • Asynchronous call without full page load
  • Real time weather using open source Yahoo API’s
  • Current auto updating Date & Time.
  • Responsive using Bootstrap

Again we need moment.js reference to your page.

The javascript will look like:

/*****************************************************************
Weather App
******************************************************************/
angCXAngularApp.service('CXWeatherService', ['$http', '$q', function ($http, $q) {
//Get the items
this.getItems = function (locid) {
var dfd = $q.defer();
var API_ROOT = "https://query.yahooapis.com/v1/public/yql?format=json";
var query = "select * from weather.forecast where woeid=" + locid + " and u='c'";
var fullUrl = API_ROOT + "&q=" + encodeURI(query);
$.ajax({
url: fullUrl,
type: "GET",
headers: { "accept": "application/json;odata=verbose" },
success: function (data) {
dfd.resolve(data.query.results.channel);
},
error: function (xhr) {
dfd.reject('Error : (' + xhr.status + ') ' + xhr.statusText + ' Message: ' + xhr.responseJSON.error.message.value);
}
});
return dfd.promise;
}
}]);
angCXAngularApp.controller('CXWeatherAppCtrl', function ($scope, CXWeatherService, $timeout) {
function setitems(weather) {
var compass = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N'];
$scope.weatherdetail = {
code: "http://l.yimg.com/a/i/us/we/52/" + weather.item.condition.code + ".gif",
temp: weather.item.condition.temp,
windchill: weather.wind.chill,
city: weather.location.city,
region: weather.location.region,
currently: weather.item.condition.text,
winddirection: compass[Math.round(weather.wind.direction / 22.5)],
windspeed: weather.wind.speed,
unitsspeed: weather.units.speed,
high: weather.item.forecast[0].high,
low: weather.item.forecast[0].low
};
}
function setTime(offset) {
var now = moment().zone(offset);
$scope.worlddate = {
today: moment(now).format("ddd, MMM DD YYYY"),
hours: moment(now).format("hh"),
minutes: moment(now).format("mm"),
seconds: moment(now).format("ss"),
ampm: moment(now).format("A")
};
}
$scope.getweather = function (location) {
CXWeatherService.getItems(location.id).then(
function (weather) {
setitems(weather);
setTime(location.offset);
},
function (reason) {
//$scope.errMessage = reason;
});
}
CXWeatherService.getItems('2180').then(function (result) {
$scope.locations = [{
'name': 'Saskatoon',
'id': '2180',
'offset': 6
},
{
'name': 'Shanghai',
'id': '2151653',
'offset': -8
},
{
'name': 'Singapore',
'id': '23424948',
'offset': -8
},
{
'name': 'Tokyo',
'id': '15015406',
'offset': -9
},
{
'name': 'Vancouver',
'id': '9807',
'offset': 7
},
{
'name': 'Portland',
'id': '2475687',
'offset': 7
}];
$scope.location = $scope.locations[0];
setitems(result);
setTime($scope.locations[0].id);
});
var tick = function () {
setTime($scope.location.offset);
$timeout(tick, 1000);
};
$timeout(tick, 1000);
});

Here we need WOEID (use this site to get WOEID for your location http://zourbuth.com/tools/woeid/ ) of location with offset X where X is (GMT + X ) value of time.
The tick function will make sure clock updates automatically.
The CSS needed here:

/* Weather */
.cx-weather-container ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.cx-weather-container ul li {
display: inline;
}
.cx-weather-img {
float: left;
width: 55px;
height: 55px;
}
.cx-weather-img img {
margin: 2px;
}
.cx-weather-temp {
margin-left: 60px;
}
.cx-weather-temp h2 {
padding: 5px;
font-weight: 600;
}
.cx-weather-temp sup {
margin-top: 3px;
font-size: 14px;
}
.cx-weather-temp h2 div {
font-size: 12px;
padding-top: 5px;
}
.cx-weather-deg {
font-size: 12px;
}
.cx-weather-detail {
float: left;
padding-left: 5px;
padding-right: 10px;
}
#ddlcxweatherlocations {
min-width: 200px;
}
.cx-weather-extra {
margin-top: -10px;
}
.cx-timedetail {
font-size: 36px;
font-weight: 600;
}
.cx-hours, .cx-minutes, .cx-seconds {
color: #FFF;
background-color: #666666;
padding: 2px;
margin: 2px 2px 0px 2px;
}
.cx-hours {
padding-left: 12px;
}
.cx-ampm {
font-size: 14px;
}
.cx-time-container {
padding-top: 10px;
float: left;
margin-left: 15px;
}
.cx-time-container h3 {
font-weight: 600;
}
.cx-weather-container h1, .cx-weather-container h2, .cx-weather-container h3, .cx-weather-container h4, .cx-weather-container h5, .cx-weather-container h6 {
color: #666666;
}

And finally the html that needed to be added in script editor web part:

<div ng-controller="CXWeatherAppCtrl">
<div id="cx-weather-app">
<div class="cx-weather-locations">
<select id="ddlcxweatherlocations" ng-init="location = locations[1]" ng-model="location" ng-options="location.name for location in locations" ng-change="getweather(location)"> </select>
</div>
<div class="cx-weather-container">
<ul>
<li class="cx-weather" ng-model="weatherdetail">
<div class="cx-weather-detail">
<div>
<div class="cx-weather-img"><img ng-src="{{weatherdetail.code}}" /></div>
<div class="cx-weather-temp">
<h2>
{{weatherdetail.temp}} <sup>&deg;C</sup>
<div class="cx-highlow">
H: {{ weatherdetail.high }}&deg; | L: {{ weatherdetail.low }}&deg;
</div>
<div class="cx-realfeal">
Real: {{weatherdetail.windchill}} &deg;
</div>
</h2>
</div>
</div>
<div class="cx-weather-extra">
Wind: {{weatherdetail.winddirection}} {{weatherdetail.windspeed}} {{weatherdetail.unitsspeed}}
</div>
</div>
</li>
<li>
<div class="cx-time-container" ng-cloak ng-model="worlddate">
<h3>
{{worlddate.today}}
</h3>
<div class="cx-timedetail">
<span class="cx-hours">
{{worlddate.hours}}
</span>:<span class="cx-minutes">
{{worlddate.minutes}}
</span>:<span class="cx-seconds">
{{worlddate.seconds}}
</span><span class="cx-ampm">
{{worlddate.ampm}}
</span>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>

You need to add reference to your javascript file also if not added to page.

That’s it.

2 thoughts on “Creating Weather & Time widget web part using Angular – SharePoint 2013

  1. Hi I have added code according to above steps. But display is not coming as I want. (I am new to angular). Please guide on this.
    My output on page:

    {{weatherdetail.temp}} °C
    H: {{ weatherdetail.high }}° | L: {{ weatherdetail.low }}°
    Real: {{weatherdetail.windchill}} °
    Wind: {{weatherdetail.winddirection}} {{weatherdetail.windspeed}} {{weatherdetail.unitsspeed}}

    1. Hi,

      Sorry for replying late.

      You need to add reference to Angularjs to content editor if not added at page layout or masterpage level.

      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
      <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
      <script src="/sites/Style%20Library/js/main.js"></script> (your javascript code file name)
      

Leave a Reply to as-agi Cancel reply

Your email address will not be published. Required fields are marked *