Introduction
In this article, we will describe how the AngularJS date picker control can be used to display events in the mini calendar view. The article discusses in detail how the mini calendar can highlight the event dates with a color and, when hovered over the date, displays the event details. This mini calendar can be added to any of the dashboards in a normal Web application and also can be used in SharePoint custom dashboards. The example uses SharePoint as the hosting environment.
Description
As described above, we are using the AngularJS date picker control as the primary control. We add styles and update the templates to display the mini calendar with highlighted events and the summary of events visible when hovered over.
The date picker uses templates to display the day, month, and year views. The default templates are available here. The location has four templates:
- Datepicker.html
- Day.html
- Month.html
- Year.html
For this scenario, we modify only two HTML files: datepicker.html and day.html.
DatePicker.html
The default content of the DatePicker.html file is as follows:
1. <div ng-switch="datepickerMode"> 2. <div uib-daypicker ng-switch-when="day" tabindex="0" class="uib-daypicker"></div> 3. <div uib-monthpicker ng-switch-when="month" tabindex="0" class="uib-monthpicker"></div> 4. <div uib-yearpicker ng-switch-when="year" tabindex="0" class="uib-yearpicker"></div> 5. </div>
Listing 1
In this example, only Line 2 requires a modification. We update Line 2 by adding a “template-url” attribute that references the modified day.html template. The updated final code looks like:
1. <div ng-switch="datepickerMode">
2. <uib-daypicker ng-switch-when="day"
template-url="../SiteAssets/CalendarCtrl/day.html"
tabindex="0"> </uib-daypicker>
3. <uib-monthpicker ng-switch-when="month"
tabindex="0"></uib-monthpicker>
4. <uib-yearpicker ng-switch-when="year"
tabindex="0"></uib-yearpicker>
5. </div>
Listing 2
Day.html
The second file that requires a modification is Day.html file. The updated file is as follows:
1. <table class="uib-daypicker" role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}"> 2. 3. <tbody> 4. <tr class="uib-weeks" ng-repeat="row in rows track by $index"> 5. <td ng-if="showWeeks" class="text-center h6"> <em>{{ weekNumbers[$index] }}</em></td> 6. <td ng-repeat="dt in row" class="uib-day text-center" role="gridcell" style="background-color:orange" id="{{::dt.uid}}" ng-class=":: dt.customClass"> 7. <button type="button" class="btn btn-default btn-sm" uib-is-class="'btn-info' for selectedDt, 'active' for activeDt on dt" ng-click="select(dt.date)" ng-disabled="::dt.disabled" tabindex="-1" title="{{::datepickerOptions.customMessage(dt)}}" onmouseenter="$(this).tooltip('show')"> 8. <span ng-class="::{'text-muted': dt.secondary, 'text-info': dt.current}">{{::dt.label}} </span> 9. </button> 10. </td> 11. </tr> 12. </tbody> 13. </table>
Listing 3
In day.html, most of the content is the same as the original template; the only change is the Line 7 “title” attribute of the button (highlighted). In the title, we refer to a custom method named “customMessage“. This method takes the current day as a parameter; in other words, dt. The “customMessage” method is defined in the main controller where the date picker is defined and referenced.
Main HTML and Controller
Now that the templates are covered, let’s look at the HTML and how the controller is used. The HTML is as below:
1. <div> 2. <script src="https://code.angularjs.org/1.4.8/angular.js" ></script> 3. <script src="https://cdn.rawgit.com/angular-ui/bootstrap/gh-pages/ ui-bootstrap-tpls-1.3.2.js"></script> 4. <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/ bootstrap.min.css" rel="stylesheet" /> 5. <div ng-app="app" ng-controller="dtController"> 6. <p class="input-group" style="width:200px;"> 7. <input datepicker-template-url="../SiteAssets/CalendarCtrl/ datepicker.html" type="text" class="form-control" is-open="isOpen" ng-model="selectedDate" uib-datepicker-popup="MM-dd-yyyy" datepicker-options="dateOptions" close-text="Close" popup-placement="bottom-left" on-open-focus="false" /> 8. <span class="input-group-btn"> 9. <button type="button" class="btn btn-default" ng-click="openCal()"> 10. <i class="glyphicon glyphicon-calendar"></i> 11. </button> 12. </span> 13. </p> 14. </div> 15. </div>
Listing 4
Lines 2-4 are references to the required JS and the CSS files. Line 7 defines the date picker control. In the date-picker definition, the important attribute that defines the custom template is the “datepicker-template-url“. It takes the relative path of the location where the modified template is stored. The datepicker-options attribute holds the background color information and the ToolTip message.
Let’s look at the controller code:
1. var app = angular.module('app', ['ui.bootstrap']); 2. app.controller('dtController', function ($scope) { 3. 4. $scope.isOpen = true; 5. $scope.events = []; 6. 7. $scope.dateOptions = { 8. customClass: highlightDay, 9. customMessage: tooltipMsg, 10. showWeeks: false 11. }; 12. init(); 13. .... 14. });
Listing 5
Lines 1-2 define the module and the controller. In line 7, dateOptions is defined. This holds the key information for highlighting the event dates and the event description. The method “highlightDay” is assigned to “customClass” and the method “tooltipMsg” is assigned to “customMessage,” which is being used in day.html ( Listing 3, Line 6 and Line 7 “title” attribute, respectively).
For this sample, the events collection defined at Line 5 has the following properties:
{ date: event1, type: 'Corporate', message: 'Event: Event1' }
“date” is a date on which the event is going to happen. “type” describes the type of event and can have two values: ‘corporate’ or ‘department’. “message” stores the event description.
In the “highlightDay” method, a CSS class name is returned, based on the type of event. For example,
1. function highlightDay(data) { 2. var date = data.date, 3. mode = data.mode; 4. 5. if (mode === 'day') { 6. var dayToCheck = new Date(date).setHours(0, 0, 0, 0); 7. for (var i = 0; i < $scope.events.length; i++) { 8. var currentDay = new Date($scope.events[i].date).setHours(0, 0, 0, 0); 9. if (dayToCheck === currentDay) { 10. if ($scope.events[i].type == "Corporate") 11. return "lime"; 12. else 13. return "orange"; 14. } 15. } 16. } 17. return ''; 18. }
The parameter “data” gets only one day at a time in the calendar. The day then is compared with the event dates and, if they match, and based on the type of event, the CSS class name is returned, (reference Lines 11 & 13). The CSS adds a background color to the day. If there are no events, there are no CSS classes returned (see Line 17).
Similarly, a ToolTip message also returns the message when the day passed as a parameter matches to the event date. For example,
1. function tooltipMsg(data) {
2. var date = data.date,
3. mode = data.mode;
4. var dayToCheck = new Date(date).setHours(0, 0, 0, 0);
5. for (var i = 0; i < $scope.events.length; i++) {
6. var currentDay =
new Date($scope.events[i].date).setHours(0, 0, 0, 0);
7. if (dayToCheck === currentDay) {
8. return $scope.events[i].message;
9. }
10. }
11. return '';
12. }
The sample CSS styles used in this example is:
<style> .lime button span { background-color: limegreen; border-radius: 32px; color: black; } .orange button span { background-color: orange; border-radius: 32px; color: black; } </style>
Now, the calendar is displayed when the button is clicked. The days are highlighted with the background color when there are one or more events on a day. When hovered on the day, it displays the event description.
Figure 1: The completed calendar
Summary
This displays a mini calendar with a summarized view of the event dates and event description. The datepicker.html and day.html templates hold the key in displaying the event description as a ToolTip. Please note that you can change only the templates you want to change and the other unmodified templates are referenced from the base definition, which is in the “ui-bootstrap-tpls” JS file.