jQuery Validate add Method dynamically - javascript

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;

Related

Switch input selection according to the time [duplicate]

This question already has answers here:
Check a radio button with javascript
(7 answers)
Closed 2 years ago.
I am currently writing a small program that saves workers as "IN" in the morning and saves "OUT", I want the program to switch the radio to "IN" in the morning and disables "OUT". The same thing in the afternoon, switch the radio to "OUT" and disables "IN"
function EnableDisable() {
var today = new Date();
var curHr = today.getHours();
if (curHr > 12) {
option1.disabled = true;
option1.disabled = false;
alert("come here");
} else {
option1.disabled = false;
option2.disabled = true;;
}
};
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-success active">
<input type="radio" class="form-control input-lg" name="status" value="in" id="option1" autocomplete="off" checked disabled="disabled"> In
</label>
<label class="btn btn-danger">
<input type="radio" name="status" value="out" id="option2" autocomplete="off" disabled="disabled"> Out
</label>
</div>
I recommend you split the functionality. You shouldn't try to handle multiplay states within the same method. Your project needs the following methods:
Init(h) the function you call once when you startup the project
CheckIn(input) the function that handles saving the checkIn time
CheckOut(input) the function that handles saving the checkOut time
Remaining functionality like disabling the IN button when it's not been checked before 12 should be its own method and could be handled with an interval.
Eventually, you would get something like this:
const init = (h) => {
const btnGroup = document.querySelector('.btn-group');
const btnSucess = btnGroup.querySelector('.btn-success input');
const btnDanger = btnGroup.querySelector('.btn-danger input');
const isMorning = h > 6 && h < 12;
const isAfternoon = h > 12 && h < 20;
if(isMorning) {
btnSucess.disabled = false;
btnDanger.disabled = true;
} else if(isAfternoon) {
btnSucess.disabled = true;
btnDanger.disabled = false;
} else {
btnSucess.disabled = true;
btnDanger.disabled = true;
}
}
const checkIn = (input) => {
input.disabled = true;
const today = new Date();
console.log(today.toString());
}
const checkOut = (input) => {
input.disabled = true;
const today = new Date();
console.log(today.toString());
}
const setup = () => {
const hours = new Date().getHours();
init(hours);
}
// Load
window.addEventListener('load', setup);
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-success active">
<input type="radio" class="form-control input-lg" name="status" value="in" id="option1" autocomplete="off" onInput="checkIn(this)"> In
</label>
<label class="btn btn-danger">
<input type="radio" name="status" value="out" id="option2" autocomplete="off" onInput="checkOut(this)" disabled> Out
</label>
</div>
This is of course not perfect code. You should check within your checkOut() function if there is a checkIn time saved. I recommend saving this time by using new Date().getTime() for doing this.
This should be enough to give you a headstart. I want to point out that your system currently isn't that flexible. If for example there is something that has to be checked-IN after 12 then you might have a problem. You should work on your business case what should happen if a user doesn't follow the model traject you have build.
Good Luck

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>

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

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

jquery Datepicker date range validation

I have a field like Born date. I have used jquery datepicker to show the calender so that user can select the date.Now I have a problem.
In the the Born date field there is a option to choose between which opens two date picker fields like
Born Date -- Between--------- ---From------- And --To----------
Now the problem is if the user selects a date in 'To field' which is less than 'From field' and press the submit button it gets submitted. I need to prevent it from submitting and display appropriate message so the user enters right date .
Please Help.
Here is the code that i am using
<input id="borndate" class="dateISO" onchange="checkDate('borndate');">
</input>
<span id="span_borndate" style="display:none">
<input id="borndate" class="dateISO" onchange="checkDate('borndate');">
</span>
This is the Java script i am using
function checkdate(fieldname) {
var comparator = '#comp_' + fieldName;
var compVal = $(comparator).val();
Value = $('#' + fieldName).val();
var fromDate = jQuery.datepicker.parseDate('mm-dd-yy', Value, null);
Values = $('#' + fieldName + '-to').val();
var toDate = jQuery.datepicker.parseDate('mm-dd-yy', Values, null);
$('#span_' + fieldName).find('.error').remove();
if (compVal == "Between") {
if (toDate < fromDate) {
$('#span_' + fieldName).append("<label class='rangeError' generated='false'>Start date should come before end date</label>");
return false;
}
}
return true;
}
And this is the function which is called again while submitting
function validateforms() {
var valid = true;
$('//classnamefor table rows which includes the date td').each(function (index) {
fieldName = $(this).attr("name");
if ($('#' + fieldName).hasClass('dateISO')) {
valid = checkDate(fieldName);
}
}
return valid;
}
Try this
http://jqueryui.com/demos/datepicker/#date-range
and make the textboxes readonly='true'
<input type="text" id="from" name="from_date" value="" readonly="true"/>
<input type="text" id="to" name="to_date" value="" readonly="true"/>

Categories