AngularJS ng-pattern function with regEx and date on year input field - javascript

I have a request from my client to add a unique form validation rule to a text input that excepts only 4 digits, no characters. The input only should take year format like 2015. The issue is that the client doesn't want the user to enter a year less than the current year and it cannot be more than 10 years past the current year.
So I created a function like this:
$scope.startYearPattern = function() {
var date = new Date();
var year = date.getFullYear();
var regex = /^[0-9]{2}$/;
if(EditProgCtrl.programDetails.academicYear > year && EditProgCtrl.programDetails.academicYear < year + 10 && regex);
};
Then on the html I have:
<div class="col-xs-6 form-horizontal program-edit" data-ng-class="{ 'has-error': programEditForm.academicYear.$invalid && programEditForm.academicYear.$touched }">
<div class="form-group required">
<label for="academicYear" class="col-xs-4 horizontal-left control-label">
Start Year
</label>
<div class="col-xs-6 program-edit">
<input type="text" ng-pattern="startYearPattern()" class="form-control input-sm" max="3000" name="academicYear" id="academicYear" data-ng-model="EditProgCtrl.programDetails.academicYear" title="Please enter a valid year" required="required" />
<div data-ng-if="programEditForm.academicYear.$touched" data-ng-messages="programEditForm.academicYear.$error">
<span class="help-block" data-ng-message="required">required field</span>
<span class="help-block" data-ng-message="pattern">Wrong Year Format</span>
</div>
</div>
</div>
</div>
It doesn't work though so I am missing something, just do not know what is wrong.

ng-pattern normally only accept pattern like ng-pattern="/^[0-9]{4}$/" i thought. I wrote u a validation directive
myModule.directive('academicYearValidation', academicYearValidation );
function academicYearValidation() {
return {
restrict: 'A',
require: 'ngModel',
link: link
}
function link (scope, element, attrs, ngModel) {
function validator(modelValue, viewValue) {
var value = modelValue || viewValue;
var date = new Date();
var year = date.getFullYear();
var regex = /^[0-9]{4}$/;
if(regex.test(value) && value > year && value < year + 10){
return true;
}else{
return false;
}
}
ngModel.$validators.academicyearvalidation = validator;
}
};
(ngModel.$validators is new in angular 1.3 before 1.3 u have to use ngModel.$parsers and ngModel.$formatters)
I made you a plunker http://plnkr.co/edit/jtCqB0zZhelQCXF6iiK6?p=preview

Related

PHP Datepicker Validate if age is lower than 18 years old

Can I do a warning validate from Datepicker and alert swal like this?
I do that and it error that is_string is not defined.
I'm new in php btw
The comment is a think that i tried to make in different way sorry abort that.
form
<div class="form-group">
<label>Birthdate</label>
<div class="input-group date">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span><input type="text" class="form-control datepicker_class" id="birth_date" name="birth_date" onchange="validateAge">
</div>
</div>
function
function validateAge(){
var birthday = new $('#birth_date').val();
// let birthday = $('#birth_date').val();
// check = explode('/',birthday);
birthday = explode("/", birthday);
// alert(check);
if (is_string(birthday)) {
birthday = strtotime(birthday);
}
// check
// 31536000 is the number of seconds in a 365 days year. strtotime for 1 years : 31556926
if(time() - birthday < 18 * 31556926) {
swal({
title: "warning",
text: "your age is lower than 18",
type: "warning"
});
}
return true;
}
In javascript there is no is_string() function. To check if variable is string you can do it this way:
if (typeof birthday === 'string' || birthday instanceof String)
//string
else
//not string

Accept date from user within particular range

I have a form through which I want to accept date only within give date range. But, which ever date I am fetching, it is returning false and showing incorrect range.
Following are the codes related-
register.html-
<div class="form-group row">
<label for="date" class="col-sm-2 col-form-label class='control-label' ">Date of Birth</label>
<div class="col-sm-5">
<input type="date" max="2010-12-31" min="1990-01-01" id="dob" placeholder="Date of birth">
</div>
</div>
controller.js-
var dobInput = document.forms["myform"]["dob"].value;
var maxdate = new Date("2010-12-31");
var mindate= new Date("1990-01-01");
if(maxdate>dobInput && dobInput>mindate)
{
alert("correct range");
}
else{
alert("Input out of range");
return false;
}
The Value you're getting is returned as a string, however you're attempting to evaluate this against Date type variables - this will not work as a string to string evaluation will be done lexicographically.
You should instead convert the value to a date first:
var inputDate = new Date(dobInput);
if(maxdate>inputDate && inputDate >mindate){
...
Your input is a string. so convert to Date first and check with getTime method. Correct code is as below..
var dobInput = document.forms["myform"]["dob"].value;
var maxdate = new Date("2010-12-31");
var mindate= new Date("1990-01-01");
var dateToChk = new Date(dobInput);
if(maxdate.getTime()>dobInput.getTime() && dobInput.getTime()>mindate.getTime())
{
alert("correct range");
}
else{
alert("Input out of range");
return false;
}

datetime comparison in ng-if

I have two DateTime objects:
time1 = '2016-04-05T15:30:00';
time2 = '2016-04-05T14:48:41.7609724Z';
In my HTML, I have:
<div ng-if="time1 > time2">result</div>. This works well.
Now I want to know if time1 minus 30 minutes still > time2. So I did:
<div ng-if="time1 - 30*60*1000 > time2">result</div> This doesn't work.
It's like I can only compare the datetime object directly using > or <, but I can't do math on it using - or +. To verify:
<div>{{time1 > time2}}</div> shows True.
<div>{{time1 < time2}}</div> shows False.
<div>{{time1 - time2}}</div> shows NaN. I expect this to be a number of the result in milliseconds.
QUESTION: How to do math on the DateTime with ng-if, e.g. adding minutes on one DateTime, then compare these two DateTime.
NOTES: Some may say it's because my time1 and time2 have different format. I've verified this is not the issue. Same issue happens when I change time2 to same format as time1.
I suggest using a filter, then you can use standard angular paradigms. Using my example your markup will look like the following:
{{date1 | myFilter: date2: '-'}}
And the filter will look something like:
.filter('myFilter', function() {
return function(date1, date2, operation) {
switch(operation) {
case '===':
return date1.toString() === date2.toString();
break;
case '-':
return (date1 - date2).toString();
break
}
}
})
here is a plunker demonstrating the concept:
https://plnkr.co/edit/gqQ0OsdR6cN7u4VM5AvP?p=preview
You could also create a controller method for the comparison of the dates.
With the Date object you can do basic math (subtraction and adding) and afterward you can get the time in millisconds with getTime() from date object.
Then you'll only have to do some scaling to minutes (*1000 *60) and you can compare the minutes.
With a $watchGroup (angular >=1.3) you can watch every variable that's relevant for an update of you time delta. You could also use ng-change on every input field but watch is easier to write.
Something like in the demo below or in this jsfiddle should work.
angular.module('demoApp', ['ui.bootstrap'])
.controller('mainController', MainController);
function MainController($scope) {
var vm = this;
vm.date1 = new Date();
vm.diff = 35;
vm.date2 = new Date(vm.date1);
vm.date2.setMinutes(vm.date1.getMinutes() + vm.diff);
vm.date = {
deltaMinutes: vm.diff,
deltaBool: Date((vm.date2 - vm.date1))
};
vm.updateDate = function(date) {
//console.log('changed', date);
var deltaDate = new Date((vm.date2 - vm.date1));
vm.date.deltaMinutes = (deltaDate.getTime() / 1000 / 60);
vm.date.deltaBool = vm.date.deltaMinutes >= vm.diff;
//console.log(vm.diff);
};
vm.open1 = function() {
vm.popup1.opened = true;
console.log('clicked open', vm.popup1);
};
vm.open2 = function() {
vm.popup2.opened = true;
};
$scope.$watchGroup(['mainCtrl.date1', 'mainCtrl.date2', 'mainCtrl.diff'], vm.updateDate);
//$scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
//$scope.format = $scope.formats[0];
//vm.altInputFormats = ['M!/d!/yyyy'];
vm.popup1 = {
opened: false
};
vm.popup2 = {
opened: false
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.1/ui-bootstrap-tpls.js"></script>
<div ng-app="demoApp" ng-controller="mainController as mainCtrl">
time difference in minutes:
<input ng-model="mainCtrl.diff"/>
<br/>date1:
<p class="input-group">
<input type="text" class="form-control" ng-model="mainCtrl.date1" is-open="mainCtrl.popup1.opened" ng-required="true" close-text="Close" uib-datepicker-popup alt-input-formats="mainCtrl.altInputFormats"/>
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="mainCtrl.open1()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
<uib-timepicker ng-model="mainCtrl.date1" ng-change="mainCtrl.changed(mainCtrl.date1)" show-meridian="ismeridian"></uib-timepicker>
date2:
<p class="input-group">
<input type="text" uib-datepicker-popup class="form-control" ng-model="mainCtrl.date2" is-open="mainCtrl.popup2.opened" ng-required="true" close-text="Close" alt-input-formats="mainCtrl.altInputFormats" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="mainCtrl.open2()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
<uib-timepicker ng-model="mainCtrl.date2" show-meridian="ismeridian"></uib-timepicker>
<br/>time difference in minutes = {{mainCtrl.date.deltaMinutes}}
<div ng-if="mainCtrl.date.deltaBool" class="alert alert-success">
date1 is at least {{mainCtrl.diff}} Minutes before date2
</div>
</div>

jQuery Validate add Method dynamically

I have a form that uses jQuery validate, but the form is generated dynamically and I am trying to add an additional method for validating whether a date is before another, if that date has been used before.
The HTML is the following (with the names generated dynamically):
<div class="form-group">
<label class="control-label col-md-2">Read Date</label>
<div class="input-group col-md-4 date date-picker" data-date-format="dd/mm/yyyy">
<div class="input-icon right">
<i class="fa"></i>
<input type="text" class="form-control insert-val" readonly="" name="datepicker_16" aria-required="true" aria-invalid="false">
</div>
<span class="help-block">Enter the date of the reading</span>
<span class="input-group-btn">
<button class="btn default" type="button" style="margin-top: -18px;"><i class="fa fa-calendar"></i></button>
</span>
</div>
<input type="hidden" name="prevdate_16" class="form-control prev-date" value="29/05/2015">
With the following jQuery to validate the date field:
$('#readingForm .insert-val').each(function(){
var prevDate = $(this).parents('.form-group').find('.prev-date').val();
var useLTD = true;
if(prevDate !== ''){
$.validator.addMethod("less_than_date", function(value, element) {
var curDate = value;
var curarr = curDate.split('/');
var curDay = curarr[0];
var curMonth = curarr[1];
var curYear = curarr[2];
var ncurDate = new Date();
ncurDate.setFullYear(curYear, curMonth-1, curDay);
var prevarr = prevDate.split('/');
var prevDay = prevarr[0];
var prevMonth = prevarr[1];
var prevYear = prevarr[2];
var nprevDate = new Date();
nprevDate.setFullYear(prevYear, prevMonth-1, prevDay);
return ncurDate <= nprevDate;
}, "The reading date must be greater than the previous reading date.");
} else {
useLTD = false;
}
$(this).rules( "add", {
required: true,
minlength: 10,
dateITA: true,
less_than_date: useLTD
});
});
Before the I added the "add method", it correctly validated the date, but now it does not, and doesnt accept even if the date is greater than the previous date.
Really stumped on this one, any help would be greatly appreciated.
Ok, as soon as I posted this, I realised that the return was the wrong way round.
Should have been:
return nprevDate <= ncurDate;

AngularJS - Check if selected date is equal to next business date

I am trying to check if selected date is equal to next business date using AngularJS. If selected date is not equal to the next business date, a warning will be shown, like twitter bootstrap's alert-warning, using ng-show angularjs directive.
Here's the current Fiddle for this.
Currently, the next business day is returned by getNextBusinessDay() $scope function. The comparison is triggered by ng-changed="comparisonResult()" which should return true/false based on comparison, but isn't working.
Here my html code:
<body ng-app="angularjs-starter" ng-controller="MainCtrl">
<div class="container">
<section id="datepicker">
<div class="bs-docs-example">
<form class="form-horizontal well">
<div class="control-group input-append">
<label for="inputDatepicker" class="label" style="margin-right:6px;">
Selected Date</label>
<input id="inputDatepicker" class="input-small" type="text"
ng-model="selectedDate" ng-changed="comparisonResult()"
data-date-format="dd/mm/yyyy" bs-datepicker>
<button type="button" class="btn" data-toggle="datepicker">
<i class="icon-calendar"></i></button>
</div>
</form>
</div>
</section>
</div>
</body>
Here's my js code:
var app = angular.module('angularjs-starter', ['$strap.directives']);
app.controller('MainCtrl', function($scope, $window, $location) {
// Datepicker directive
$scope.selectedDate = null;
$scope.getNextBusinessDay = function() {
return $scope.getDeliveryDateObj(1);
}
$scope.getDeliveryDateObj = function(businessDaysLeftForDelivery){
var now = new Date();
var dayOfTheWeek = now.getDay();
var calendarDays = businessDaysLeftForDelivery;
var deliveryDay = dayOfTheWeek + businessDaysLeftForDelivery;
if (deliveryDay >= 6) {
businessDaysLeftForDelivery -= 6 - dayOfTheWeek; // deduct this-week days
calendarDays += 2; // count this coming weekend
deliveryWeeks = Math.floor(businessDaysLeftForDelivery / 5); // how many whole weeks?
calendarDays += deliveryWeeks * 2; // two days per weekend per week
}
now.setTime(now.getTime() + calendarDays * 24 * 60 * 60 * 1000);
now.setUTCHours(0);
now.setUTCMinutes(0);
now.setUTCSeconds(0);
now.setUTCMilliseconds(0);
return now;
}
$scope.getNextBusinessDay();
$scope.comparisonResult = function() {
if($scope.selectedDate == $scope.getNextBusinessDay()) {
return false;
} else {
return true;
}
};
});
Any help or suggestion will be appreciated. Thanks in advance. :)
When comparing dates, use a.getTime() == b.getTime() instead of a == b.
It is 2017 now, if you use Angular >= v1.2 you can use angular.equals(date1, date2)

Categories