Reputation: 295
I have implemented a date picker with validations in my Angular App.
HTML :
<div class="control-group">
<label class="control-label" for="reservation.reservedFrom">Reserved From<sup>*</sup></label>
<div class="controls input-group date" data-provide="datepicker">
<!--<input type="text" class="span4" style="width:150px" name="reservedFrom" placeholder="Reserved From" ng-model="reservation.reservedFrom" ng-change='checkErr()'
validator="required" required-error-message="Date is required" id="startDate122" />-->
<input class="form-control" type="text" name="startDate" core-date-picker ng-model="reservation.reservedFrom" >
<div class="input-group-addon">
<span class="glyphicon glyphicon-th"></span>
</div>
<span style="color:red">{{errMessageFrom}}</span>
</div> <!-- /controls -->
</div> <!-- /control-group -->
<div class="control-group">
<label class="control-label" for="reservation.reservedTill">Reserved Till<sup>*</sup></label>
<div class="controls input-group date" data-provide="datepicker">
<!--<input type="text" style="width:150px" class="span4" name="reservedTill" placeholder="Reserved Till" data-ng-model="reservation.reservedTill"
validator="required" required-error-message="Date is required" valid-method="watch" id="endDate" ng-change='checkErr()' />-->
<input class="form-control" type="text" name="EndDate" core-date-picker ng-model="reservation.reservedTill" ng-change='checkErr()' id="endDate1">
<div class="input-group-addon">
<span class="glyphicon glyphicon-th"></span>
</div>
<span style="color:red">{{errMessageTo}}</span>
</div> <!-- /controls -->
</div> <!-- /control-group -->
Controller :
myApp.controller('editReservationController', ['$scope', '$filter', 'reservationResolved', 'pocResolved', 'accountResolved', 'reservationServices', '$location', '$state',
function ($scope, $filter, reservationResolved, pocResolved, accountResolved, reservationServices, $location, $state) {
$scope.reservation = new Object();
$scope.accounts = accountResolved.data;
$scope.pocs = pocResolved.data;
$scope.reservation.employee = reservationResolved.data;
$scope.updateReservation = function () {
var from = $scope.reservation.reservedFrom;
var till = $scope.reservation.reservedTill;
if ($scope.editReservationForm.$valid && $scope.checkErr()) {
var from = $scope.reservation.reservedFrom;
var till = $scope.reservation.reservedTill;
//var t = $scope.checkErr();
//TODO: fix it properly
$scope.reservation.reservedTill = '';
$scope.reservation.reservedFrom = '';
$scope.reservation.reservedFrom = $('#startDate').val();
$scope.reservation.reservedTill = $('#endDate').val();
reservationServices.updateReservation($scope.reservation).then(function (result) {
$scope.data = result.data;
if (!result.data.error) {
$state.transitionTo('employeeTalentPool', {
id: $state.params.id
});
}
});
}
};
$scope.cancel = function () {
$location.path("/reservations");
};
$scope.$watch("reservation.reservedFrom", function (newValue, oldValue) {
$scope.checkErr();
});
$scope.$watch("reservation.reservedTill", function (newValue, oldValue) {
$scope.checkErr();
});
$scope.getCurrentDate = function() {
var utcDate = new Date();
var isoExtendedDate = utcDate.toISOString();
var isoSimpleDate = isoExtendedDate.split("T")[0];
return isoSimpleDate;
}
$scope.checkErr = function () {
var startDateStr = $scope.reservation.reservedFrom;
var endDateStr = $scope.reservation.reservedTill;
var startDate;
if (startDateStr != undefined) {
startDate = new Date(startDateStr);
}
var endDate;
if (endDateStr != undefined) {
endDate = new Date(endDateStr);
}
$scope.errMessageFrom = '';
$scope.errMessageTo = '';
var myDate = new Date(); // Set this to your date in whichever timezone.
var utcDate = myDate.toUTCString();
if (startDate != undefined && startDate < new Date()) {
$scope.errMessageFrom = 'Start Date should be greater than or equal to present day.';
return false;
}
if (endDate != undefined && new Date(endDate) < new Date()) {
$scope.errMessageTo = 'End Date should be greater than or equal to present day.';
return false;
}
if (startDate != undefined && endDate != undefined && endDate <= startDate) {
$scope.errMessageTo = "End date must be after start day.";
return false;
}
return true;
};
}]);
App.js :
//Date Picker
myApp.directive('coreDatePicker', function ($compile) {
return {
restrict: 'A',
require: 'ngModel',
compile: function (element, attrs) {
$(element[0]).datepicker({
autoclose: true,
format: "dd/mm/yyyy"
});
return this.link;
},
link: function (scope, element, attrs, ngModelCtrl) {
$(element[0]).datepicker().on("change", function (e) {
scope.$apply(function () {
ngModelCtrl.$setViewValue(element.val());
});
});
}
};
});
I will explain the scenario I am talking about.
Issue 1 - I selected a date from the calendar and it was displayed correctly in the date-picker text box. I then clicked on the date picker again to select a different date but then I decided not to change the currently selected date, so I clicked outside the calendar without selecting a date for the second time. Since I did not select a date the second time, the date picker cleared the firstly selected date from the text box making it a null. I don't want that to happen. I want the firstly selected date to remain there unless a different date is selected (not a null value).
Issue 2 - While validating the dates, I am having trouble with comparing the selected date with the current date. If the selected date is lesser than current date, the error message should be displayed. But in my case the error is getting displayed if I select the same date as today. It should allow me to select the current day.
I have used Bootstrap-datepicker. Please let me know if more information is required.
Thanks in advance.
Upvotes: 2
Views: 2855
Reputation: 4928
At a quick glance i noticed ,
link: function (scope, element, attrs, ngModelCtrl) {
$(element[0]).datepicker().on("change", function (e) {
scope.$apply(function () {
ngModelCtrl.$setViewValue(element.val());
});
});
}
Should fire onchange right? What i understand from Issue 1 is that it fires regardless if there is change or not. Have you thought of trying some checkings at
$(element[0]).datepicker().on("change", function (e) {
scope.$apply(function () {
ngModelCtrl.$setViewValue(element.val());
});
});
Try
$(element[0]).datepicker().on("change", function (e) {
scope.$apply(function () {
if(element.val()) {
ngModelCtrl.$setViewValue(element.val());
}
});
});
Just a little check on the element.val() for a try wouldn't harm.
For issue two, I don't think you can compare the date that way.
new Date()
returns
Thu Oct 20 2016 14:54:17 GMT+0800 (Malay Peninsula Standard Time)
What is your startDateStr
Noticed new Date()
has some seconds and milliseconds.
If you just want to compare days , month and years that is (DD/MM/yyyy)
i suggest you convert your dates before you can compare.
Or compare individually like
startDate.getDate() < new Date().getDate() // To compare a day
FOr a better option iw ould suggest moment. Github.
var startDate = moment(startDateStr, 'MM-DD-YYYY').format('MMMM D');
var today = moment().format('D MMM, YYYY');
if (startDate != undefined && startDate < today) {
}
Update
Have you tried moving the checking to
$scope.$watch("reservation.reservedFrom", function (newValue, oldValue) {
if(newValue && newValue !== oldValue) {
$scope.checkErr();
}
});
$scope.$watch("reservation.reservedTill", function (newValue, oldValue) {
if(newValue && newValue !== oldValue) {
$scope.checkErr();
}
});
When you use <= or >= to compare two date objects, they are compared via valueOf, which is the same as getTime for Date.
But when you use ==, they are two different objects of the same type, so it returns false.
So in your case ^To compare the two dates. The correct way is
var startDate = moment(startDateStr, 'MM-DD-YYYY').format('MMMM D');
var today = moment().format('D MMM, YYYY');
if (startDate != undefined && startDate.getTime() < today.getTime()) {
}
These explanation is taken Here . You can check the link for more explanation.
The getTime
convert the date into an epoch equivalent which is basically numerical/numbers values which can be comapred. new Date()
is an object and so is new Date('10/20/2016')
and object A cannot be equal to object b. To understand this more you can try on your browser console.
new Date() === new Date();
> false
but
new Date().getTime() === new Date().getTime()
>true;
The first is false is false because you are comparing two objects. The second is equivalent to comparing to numeric values. Afterall
new Date().getTime()
>1477011127232
Upvotes: 1