Load AngularJS, dependencies script files and the script file angular-reservation.min.js in your index.html.
<!-- Angular reservation dependencies -->
<script type="text/javascript" src="bower_components/angular-bootstrap/ui-bootstrap.min.js"></script>
<script type="text/javascript" src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
<script type="text/javascript" src="bower_components/angular-translate/angular-translate.min.js"></script>
<script src="bower_components/angular-messages/angular-messages.min.js"></script>
<!-- Angular reservation minified -->
<script type="text/javascript" src="bower_components/angular-reservation/dist/angular-reservation.min.js"></script>
Load styles
Load bootstrap css and angular-reservation.min.css in your index.html.
<!-- Compiled and minified Bootstrap CSS -->
<link rel="stylesheet" href="components/bootstrap/bootstrap.min.css">
<!-- Angular reservation minified css -->
<link rel="stylesheet" href="bower_components/angular-reservation/dist/angular-reservation.min.css">
Add module dependency
Add 'hm.reservation' to the list of module dependencies.
angular.module('myApp', [
'hm.reservation'
])
HTML Markup
Add angular-reservation directive in an html page.
<!-- angular-reservation directive -->
<reservation></reservation>
Setup
//Configuration of reservation module
angular.module('myApp').config(function (reservationConfigProvider) {
var config = {
getAvailableHoursAPIUrl: "http://API-URL/availableHours", //API url endpoint to load list of available hours
reserveAPIUrl: "http://API-URL/reserve", //API url endpoint to do a reserve
};
reservationConfigProvider.set(config);
});
You can configure angular-reservation module during config phase passing configuration options.
//Configuration of reservation module
angular.module('myApp').config(function (reservationConfigProvider) {
var config = {
getAvailableDatesFromAPI: false,
getAvailableDatesAPIUrl: "http://api-url/api/availableDates",
getAvailableHoursAPIUrl: "http://api-url/api/availableHours",
reserveAPIUrl: "http://api-url/api/reserve",
language: "es",
dateFormat: "dd/MM/yyyy",
showConfirmationModal: false,
datepickerTemplate: "partials/datepicker.html",
availableHoursTemplate: "partials/availableHours.html",
noAvailableHoursTemplate: "partials/noAvailableHours.html"
clientFormTemplate: "partials/clientFormTemplate.html",
confirmationModalTemplate: "partials/confirmModal.html"
};
reservationConfigProvider.set(config);
});
Loading available dates from a REST API
//Configuration of reservation module
angular.module('myApp').config(function (reservationConfigProvider) {
var config = {
getAvailableDatesFromAPI: true,
getAvailableDatesAPIUrl: "http://my-api-url/availableDates",
...
};
reservationConfigProvider.set(config);
});
Overriding datepicker template
<h3 class="text-center">Select an available date</h3>
<div style="width: 50%; margin: 0 auto">
<p class="input-group">
<input type="text" class="form-control" uib-datepicker-popup ng-model="reservationCtrl.selectedDate" is-open="isOpen"
datepicker-options="reservationCtrl.datepickerOptions" ng-change="reservationCtrl.onSelectDate()"/>
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="isOpen = !isOpen"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
Overriding available hours template
<h3 class="text-center">Select an available hour</h3>
<div ng-repeat="hour in reservationCtrl.availableHours" ng-click="reservationCtrl.selectHour(hour)">
<div ng-class="{'selected': reservationCtrl.selectedHour == hour}" class="hour">
<span>{{hour}}</span>
</div>
</div>
<style>
.hour{
border: 1px solid black;
border-radius: 4px;
text-align: center;
padding: 1em 1em;
margin: 1em 1em;
cursor: pointer;
}
</style>
Overriding no available hours template
<div>
<h3 class="text-justify" style="padding: 2em 2em;">Oh no! There is no available hours for selected date, try another date!</h3>
</div>
Overriding client form template
<div class="form-group col-md-12">
<label class="col-md-4 control-label" for="name">Name</label>
<div class="col-md-8">
<input id="name" name="name" class="form-control" placeholder="{{'name' | translate}}" type="text" ng-model="reservationCtrl.userData.name"
autofocus="true" ng-pattern="/^[\w\s\-\x7f-\xff]*$/" ng-minlength="2" ng-maxlength="100" required>
<div class="help-block" ng-messages="reserveForm.name.$error" ng-if="reserveForm.$submitted">
<p ng-message="minlength" class="text-danger">{{"minLength" | translate: '{minLength: "2"}'}}</p>
<p ng-message="maxlength" class="text-danger">{{"maxLength" | translate: '{maxLength: "100"}'}}</p>
<p ng-message="pattern" class="text-danger">{{"invalidCharacters" | translate}}</p>
<p ng-message="required" class="text-danger">{{"required" | translate}}</p>
</div>
</div>
</div>
<div class="form-group col-md-12">
<label class="col-md-4 control-label">Gender</label>
<div class="col-md-8">
<div class="radio">
<label>
<input type="radio" name="gender" id="option1" value="Male" ng-model="reservationCtrl.userData.gender">
Male
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="gender" id="option2" value="Female" ng-model="reservationCtrl.userData.gender">
Female
</label>
</div>
<div class="help-block" ng-messages="reserveForm.gender.$error" ng-if="reserveForm.$submitted">
<p ng-message="required" class="text-danger">{{"required" | translate}}</p>
</div>
</div>
</div>
<div class="form-group col-md-12">
<label class="col-md-4 control-label" for="phone">Phone</label>
<div class="col-md-8">
<input id="phone" name="phone" class="form-control" placeholder="{{'phone' | translate}}" type="tel" ng-model="reservationCtrl.userData.phone"
ng-pattern="/^[0-9]*$/" ng-minlength="5" ng-maxlength="15" required>
<div class="help-block" ng-messages="reserveForm.phone.$error" ng-if="reserveForm.$submitted">
<p ng-message="minlength" class="text-danger">{{"minLength" | translate: '{minLength: "5"}'}}</p>
<p ng-message="maxlength" class="text-danger">{{"maxLength" | translate: '{maxLength: "15"}'}}</p>
<p ng-message="pattern" class="text-danger">{{"invalidPhone" | translate}}</p>
<p ng-message="required" class="text-danger">{{"required" | translate}}</p>
</div>
</div>
</div>
<div class="form-group col-md-12">
<label class="col-md-4 control-label" for="age">Age</label>
<div class="col-md-8">
<select id="age" name="age" class="form-control" ng-model="reservationCtrl.userData.age" required>
<option value="18-25">Between 18 and 25</option>
<option value="25-40">Between 25 and 40</option>
<option value="40-65">Between 40 and 65</option>
<option value="+65">>65/option>
</select>
<div class="help-block" ng-messages="reserveForm.age.$error" ng-if="reserveForm.$submitted">
<p ng-message="required" class="text-danger">{{"required" | translate}}</p>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<button id="reserve" type="submit" name="reserve" class="btn btn-success">{{"reserve" | translate}}</button>
</div>
</div>
Overriding confirmation modal template
<div class="modal-header">
<h3 class="modal-title">Confirm amazing stuff</h3>
</div>
<div class="modal-body">
<h4>Are you really really sure of what you are doing??</h4>
<h5>Let's the party started!!!</h5>
</div>
<div class="modal-footer">
<button class="btn btn-danger" type="button" ng-click="$dismiss()">Oh, no!</button>
<button class="btn btn-success" type="button" ng-click="$close()">Hell, yes!</button>
</div>
You can pass datepicker options to angular-reservation directive to configure datepicker based on your needs. Datepicker option documentation can be found here.
HTML Markup
<reservation datepicker-options="myCtrl.datepickerOptions"></reservation>
Controller
//Controller
angular.module('myApp').controller('MyCtrl', function () {
var vm = this;
//Datepicker options
vm.datepickerOptions = {
minDate: new Date(), //Disabled date selection before today
showWeeks: false, //Don't show weeks
startingDay: 1, //Starting day at Monday
dateDisabled: myDisabledDates //Disabled dates
}
//Disabled dates
function myDisabledDates(dateAndMode) {
var date = dateAndMode.date;
var mode = dateAndMode.mode;
var day = date.getDate();
var dayOfWeek = date.getDay();
var month = date.getMonth();
//Disable dates on Sundays and from 1 to 15 of August
return (mode === 'day' && (dayOfWeek === 0) || (month === 7 && day in [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]));
}
});
There are some callbacks available at reservationService that can be use to do some business logic. Open browser console to see callback logging for demo.
angular.module('myApp').controller('MyCtrl', function ($q, reservationService) {
var vm = this;
//Reservation module callbacks
reservationService.onBeforeGetAvailableHours = function(selectedDate) {
console.log("Before get available hours! Selected date: " + selectedDate);
var deferred = $q.defer();
deferred.resolve();
return deferred.promise;
}
reservationService.onCompletedGetAvailableHours = function(statusLevel, message, selectedDate) {
console.log("Completed get available hours! Status level: " + statusLevel + ", message: " + message + ", selected date: " + selectedDate);
}
reservationService.onSuccessfulGetAvailableHours = function(statusLevel, message, selectedDate, availableHours) {
console.log("Successful get available hours! Status level: " + statusLevel + ", message: " + message + ", selected date: " + selectedDate + ", availableHours: " + availableHours);
}
reservationService.onErrorGetAvailableHours = function(statusLevel, message, selectedDate) {
console.log("Error get available hours! Status level: " + statusLevel + ", message: " + message + ", selected date: " + selectedDate);
}
reservationService.onBeforeReserve = function(selectedDate, selectedHour, userData) {
console.log("Before reserve! Selected date: " + selectedDate + ", selected hour: " + selectedHour + ", userData: " + JSON.stringify(userData));
var deferred = $q.defer();
deferred.resolve();
return deferred.promise;
}
reservationService.onCompletedReserve = function(statusLevel, message, selectedDate, selectedHour, userData) {
console.log("Completed reserve! Status level: " + statusLevel + ", message: " + message + ", selected date: " + selectedDate + ", selectedHour: " + selectedHour + ", userData: " + JSON.stringify(userData));
}
reservationService.onSuccessfulReserve = function(statusLevel, message, reservedDate, reservedHour, userData) {
console.log("Success reserve! Status level: " + statusLevel + ", message: " + message + ", reserved date: " + reservedDate + ", reserved hour: " + reservedHour + ", userData: " + JSON.stringify(userData));
}
reservationService.onErrorReserve = function(statusLevel, message, selectedDate, selectedHour, userData) {
console.log("Error reserve! Status level: " + statusLevel + ", message: " + message + ", selected date: " + selectedDate + ", selected hour: " + selectedHour + ", userData: " + JSON.stringify(userData));
}
});