angular.module('plunker', ['dateInput'])
.controller('MainCtrl', ['$scope', '$log', function($scope, $log) {
var dates = [];
for (i = 0; i < 10; i++) {
dates.push(new Date());
}
$scope.dates = dates;
$scope.changeMe = function(oldValue, newValue) {
$log.info('Changed ' + oldValue + ' - ' + newValue);
}
}]);
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.2.x" src="https://code.angularjs.org/1.2.25/angular.js" data-semver="1.2.25"></script>
<script src="dateInput.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="date in dates">
<date-input value="date" on-change="changeMe"></date-input>
<p>
{{date}}
</div>
</body>
</html>
/* Put your css in here */
.dateinput {
-webkit-appearance: none;
font-size: 14px;
font-family: sans-serif;
border: 1px solid #ccc;
border-radius: 0px;
padding: 1px;
padding-left: 2px;
background-color: #eee;
}
my-date-input {
font-size: 14px;
font-family: sans-serif;
}
angular.module('dateInput', [])
/**
* Directive to provide input fields for a date. Only hour and minute
* can be changed.
*
* Matches only the element name: <date-input ...></date-input>
*
* Attributes:
* value - The date value that is displayed. Can be either a timestamp
* (long) or Date.
* on-change - Name of the function in the scope that is triggered when
* the date is changed.
*/
.directive('dateInput', ['$compile', '$log', function($compile, $log) {
// Utility methods
function pad(value) {
if (value < 10) {
return '0' + value;
}
return value;
}
function list(max) {
var result = [];
for (i = 0; i < max; i++) {
result.push(pad(i));
}
return result;
}
// Handlers for the input type. The input type can be both, a timestamp
// (long) or a Date.
var handleNumber = function(d) {
return d.getTime();
};
var handleDate = function(d) {
return new Date(d);
};
// List values
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
var minutes = list(60);
var hours = list(24);
return {
restrict: 'E',
scope: {
value: '='
},
link: function(scope, element, attr) {
var timestamp = scope.value;
var handle = typeof timestamp === 'number' ? handleNumber : handleDate;
var date = new Date(timestamp);
var day = date.getDate();
var month = months[date.getMonth()];
var year = date.getFullYear();
var hour = date.getHours();
var minute = date.getMinutes();
scope.hour = pad(hour);
scope.minute = pad(minute);
scope.hours = list(24);
scope.minutes = list(60);
element.append(day + '-' + month + '-' + year);
function createSelect(name) {
element.append('<select class="dateinput ' + name + '" ng-model="' + name + '" ng-options="' + name + ' for ' + name + ' in ' + name + 's"></select>')
}
createSelect('hour');
element.append(':');
createSelect('minute');
$compile(element.contents())(scope);
function createWatch(name) {
scope.$watch(name, function(newValue, oldValue){
if (newValue === oldValue) {
return;
}
var oldDate = handle(date);
var funcName = 'set' + name[0].toUpperCase() + name.slice(1) + 's';
date[funcName](newValue);
var newDate = handle(date);
scope.value = newDate;
// Call the provided change function in the parent scope.
scope.$parent[attr.onChange](oldDate, newDate);
});
}
createWatch('hour');
createWatch('minute');
}
};
}]);