I have two dates to be compared in the following format
the response coming from backend service has following date format
alignFillDate - 2015-06-09
pickUpDate - 2015-05-10
so, front end needs to check the condition is if pickUpDate is less then the alignFillDate, we will increase the alignFillDate by 30 days, i.e, we increment the pickUpDate to next month(30 days from now ) and show different text on view
How, do i achieve this using angular and javascript. ? how does my html and controller needs to changed for this date calculation
You save those date strings as Date objects, do a comparison with vanilla javascript and assign to scope or this.
var alignFillDate = new Date("2015-06-09");
var pickUpDate = new Date("2015-05-10");
if (pickUpDate < alignFillDate) {
alignFillDate = alignFillDate.setDate(alignFillDate.getDate() + 30);
}
$scope.pickUpDate = pickUpDate;
$scope.alignFillDate = alignFillDate;
Here is a plunk that does what you are trying to do http://plnkr.co/edit/Kq7WA1cBcrwDyxDeBFAL?p=info.
You should use an angular filter to achieve this. The filter takes in the object containing both dates, and will return the formatted date.
Here is a filter that performs this operation:
myApp.filter('customDate', function($filter) {
var DATE_FORMAT = 'yyyy-MM-dd';
return function (input) {
var alignFillDate = new Date(input.alignFillDate);
var pickUpDate = new Date(input.pickUpDate);
if ( alignFillDate > pickUpDate) {
alignFillDate.setDate(alignFillDate.getDate() + 30)
alignFillDate = $filter('date')(alignFillDate, DATE_FORMAT);
return alignFillDate + ' this date has been changed';
} else {
return $filter('date')(alignFillDate, DATE_FORMAT);
}
}
});
Here is a working jsFiddle: http://jsfiddle.net/ADukg/6681/
Other way -- doing "from scratch": (Example in AngularJS). The method isAfterDate(), specifically, returns true if the first date is greater than second date.
Below, date_angular.js:
var DateModule = angular.module("dates", []);
DateModule.controller("dates", function($scope){
$scope.filtros = {};
$scope.filtros.data_first = null;
$scope.filtros.data_second = null;
$scope.isAfterDate = function(){
data_first_day = $scope.filtros.data_first.split("/")[0];
data_first_month = $scope.filtros.data_first.split("/")[1];
data_first_year = $scope.filtros.data_first.split("/")[2];
data_second_day = $scope.filtros.data_second.split("/")[0];
data_second_month = $scope.filtros.data_second.split("/")[1];
data_second_year = $scope.filtros.data_second.split("/")[2];
if(data_first_year > data_second_year){
return true;
}else if (data_first_year == data_second_year){
if((data_first_month > data_second_month)){
return true;
}else if ((data_first_month < data_second_month)) {
return false;
}else{
if(data_first_day == data_second_day){
return false;
}else if (data_first_day > data_second_day){
return true;
}else{
return false;
}
}
}else{
return false;
}
}
$scope.submit = function() {
if (this.isAfterDate()){
alert("The first date is grater than the second date");
}else{
$("#form_date").submit();
}
}
});
RelatoriosModule.directive("datepicker", function () {
return {
restrict: "A",
require: "ngModel",
link: function (scope, elem, attrs, ngModelCtrl) {
var updateModel = function (dateText) {
scope.$apply(function () {
ngModelCtrl.$setViewValue(dateText);
});
};
var options = {
dateFormat: "dd/mm/yy",
onSelect: function (dateText) {
updateModel(dateText);
}
};
elem.datepicker(options);
}
}
});
For other comparisons: only adjust the method.
In the form (form.html), if you are using AngularJS, you can add it in your archive. Below, form.html:
<div ng-app="dates" class="section-one">
<div ng-controller="dates" class="section">
<form method="get" action="dates/dates" id="form_date">
<div class="form-container--linha">
<div class="field-3">
<label for="data_first">first date: </label>
<input id="data_first" type="text" name="data_first" ng-model="filtros.data_first" datepicker/>
</div>
<div class="field-3">
<label for="data_second">second date: </label>
<input id="data_second" type="text" name="data_second" ng-model="filtros.data_second" datepicker/>
</div>
</div>
<div class="actions">
<button class="bt-principal" type="button" ng-click="submit()">submit</button>
</div>
<form>
</div>
</div>
Related
So I am using the air-datepicker (http://t1m0n.name/air-datepicker/docs/)
to select a month, presetting to 01/03/2018 for example, which fills a hidden field in my input called startdate2 using the altmethod.
What I want is to update enddate2 with startdate2 + 2 months. I've tried using onChange and a few various methods but nothing seems to be working.
<input type="hidden" name="startdate" id="startdate2" value="" class="inputdate" onChange="getDateAhead()" >
<input type="hidden" name="enddate" id="enddate2" value="" class="outputdate" >
<script>
function getDateAhead()
{
var start = document.getElementById('startdate2').value;
var end = start.setMonth(start.getMonth()+2);
document.getElementById('enddate2').value = end;
}
</script>
Just can't seem to get it working??
Please check documentation(http://t1m0n.name/air-datepicker/docs/) for the datepicker you are using. Your concern function is onSelect.
var eventDates = [1, 10, 12, 22],
$picker = $('#custom-cells'),
$content = $('#custom-cells-events'),
sentences = [ … ];
$picker.datepicker({
language: 'en',
onRenderCell: function (date, cellType) {
var currentDate = date.getDate();
// Add extra element, if `eventDates` contains `currentDate`
if (cellType == 'day' && eventDates.indexOf(currentDate) != -1) {
return {
html: currentDate + '<span class="dp-note"></span>'
}
}
},
onSelect: function onSelect(fd, date) {
var title = '', content = ''
// If date with event is selected, show it
if (date && eventDates.indexOf(date.getDate()) != -1) {
title = fd;
content = sentences[Math.floor(Math.random() * eventDates.length)];
}
$('strong', $content).html(title)
$('p', $content).html(content)
}
})
UPDATE: IT HAS BEEN CONFIRMED THAT THIS IS AN ANGULAR BUG
Check: https://github.com/angular/angular.js/issues/14734#issuecomment-224558516
The case is, I am trying to create a datepicker field that detects if the input is an invalid date(The months and days validity is also included like 2015-02-30 is invalid because there is no February 30) and is also required. So, I created a custom form validity via directive to detect the invalid date. The custom validity is working fine, however, seems like the $error.required and $invalid does not sync since I have used "ngModel.$validators.available".
Here is a working plunker: http://plnkr.co/edit/NuDGB64IetpcsaVB03T7?p=preview
You will notice in plunker that the $error.required is true but the $invalid is Just blank but turns to true when you input an invalid date and false if the date input is valid. In short, the form is not considered invalid when the input is blank which is very needed for my ng-class
The code is:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/flick/jquery-ui.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script type="text/javascript" src="https://code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
</head>
<body>
<form ng-controller="myCtrl" name="bioManagementForm" novalidate>
Degree: <br />
<p>Invalid Input: -- {{ bioManagementForm.in_company_since.$invalid }}</p>
<p>Required -- {{ bioManagementForm.in_company_since.$error.required }}</p>
<input class="form-control input-form since" ng-class="{ 'error': bioManagementForm.in_company_since.$invalid && notifications }" type="text" id="in_company_since" name="in_company_since" ng-model="input.in_company_since" ng-required="true" datepicker>
</form>
</body>
<script>
// Code goes here
var myApp = angular.module('myApp', []);
myApp.controller('myCtrl', function($scope){
});
myApp.directive('datepicker', function() {
return {
restrict: 'A',
require : 'ngModel',
link : function (scope, element, attrs, ngModel) {
console.log(ngModel);
datePatternCounter = [];
// $(function(){
if(!scope.viewOnly){
element.attr("placeholder", "YYYY-MM-DD");
}
element.datepicker({
changeYear: true,
changeMonth: true,
yearRange: "1900:+50",
showButtonPanel: true,
closeText: 'Clear',
dateFormat:'yy-mm-dd',
onSelect:function (date) {
ngModel.$setViewValue(date);
scope.$apply();
},
// Custom function that clears the date value of the model when the "Clear" button is clicked on the datepicker
onClose: function(date){
var event = arguments.callee.caller.caller.arguments[0];
if(Number(date) && date.length == 8){
// alert("dean");
year = date.slice(0, 4);
month = date.slice(4, 6);
day = date.slice(6, 8);
newDate = year+"-"+month+"-"+day;
ngModel.$setViewValue(newDate);
ngModel.$render();
}else{
// alert("armada");
// Code if with dash
// Do nothing
}
// ngModel.$error.datePattern
if(event['type'] == 'click'){
ngModel.$setViewValue(undefined);
ngModel.$render();
}
},
beforeShow: function (e, t) {
id = document.querySelector( '#ui-datepicker-div' );
angular.element(id).addClass('HideTodayButton');
if(element.hasClass('birth_date')){
element.datepicker("option", "maxDate", 0);
}
},
});
// });
// START Syntax to check if the date is valid or not in real time
ngModel.$validators.available = function (modelValue, viewValue) {
if(modelValue){
var check = modelValue.split('-');
var y = parseInt(check[0], 10);
var m = parseInt(check[1], 10);
var d = parseInt(check[2], 10);
var date = new Date(y,m-1,d);
if (date.getFullYear() == y && date.getMonth() + 1 == m && date.getDate() == d) {
check = true;
} else {
check = false;
name = ngModel.$name;
if(datePatternCounter.indexOf(name) == -1){
datePatternCounter.push(name);
element.parent().siblings("span.errors").append('<span class="invalid-date" ng-if="'+ngModel.$error.available+'"> * Invalid Date <br /></span>');
}
}
}
return check;
}
// END Syntax to check if the date is valid or not
}
}
});
</script>
</html>
Change your date validator to return true in case of empty value:
ngModel.$validators.available = function (modelValue, viewValue) {
if(modelValue){
var check = modelValue.split('-');
var y = parseInt(check[0], 10);
var m = parseInt(check[1], 10);
var d = parseInt(check[2], 10);
var date = new Date(y,m-1,d);
if (date.getFullYear() == y && date.getMonth() + 1 == m && date.getDate() == d) {
check = true;
} else {
check = false;
name = ngModel.$name;
if(datePatternCounter.indexOf(name) == -1){
datePatternCounter.push(name);
element.parent().siblings("span.errors").append('<span class="invalid-date" ng-if="'+ngModel.$error.available+'"> * Invalid Date <br /></span>');
}
}
return check; // true or false when value is not empty
}
return true; // empty value should be handled by ng-required, we only check format here, so return true
}
I currently have this filter on my table
(function(document) {
'use strict';
var LightTableFilter = (function(Arr) {
var _input;
function _onInputEvent(e) {
_input = e.target;
var tables = document.getElementsByClassName(_input.getAttribute('data-table'));
Arr.forEach.call(tables, function(table) {
Arr.forEach.call(table.tBodies, function(tbody) {
Arr.forEach.call(tbody.rows, _filter);
});
});
}
function _filter(row) {
var text = row.textContent.toLowerCase(), val = _input.value.toLowerCase();
row.style.display = text.indexOf(val) === -1 ? 'none' : 'table-row';
}
return {
init: function() {
var inputs = document.getElementsByClassName('light-table-filter');
Arr.forEach.call(inputs, function(input) {
input.oninput = _onInputEvent;
});
}
};
})(Array.prototype);
document.addEventListener('readystatechange', function() {
if (document.readyState === 'complete') {
LightTableFilter.init();
}
});
})(document);
I'm wondering how i can use two date fields with this to act as a date range? i have just tried adding two date fields in but that just gives me the response of two exact dates, not the range in between
Heres my html code for the dates
<label for="Date">Date From:</label>
<input type="date" id="datefrom" class="light-table-filter form-control" style="width:50%" data-table="order-table" placeholder="Filter">
<label for="Date">Date to:</label>
<input type="date" id="dateto" class="light-table-filter form-control" style="width:50%" data-table="order-table" placeholder="Filter">
I think this will need some expanding of you filter function, but you can compare dates with compare operators like >= and <=.
So you need to create dates of your 2 input fields and a date of the table row value. You need to identify the cell if it is indeed the date cell, otherwise it will create date objects of arbitrary cell values. I don't know your full HTML, but this can be done by adding a class, for example (see my code).
For example:
function _filter(row) {
var dateFrom = new Date(document.getElementById('datefrom').value);
var dateTo = new Date(document.getElementById('dateto').value);
dateFrom.setHours(0);
dateTo.setHours(0);
var text = row.textContent.toLowerCase(),
val = _input.value.toLowerCase();
row.style.display = text.indexOf(val) === -1 ? 'none' : 'table-row';
if (!isNaN(dateFrom.getTime()) && !isNaN(dateTo.getTime())) {
var cell = row.querySelectorAll(".date")[0];
var arr = cell.innerText.split('-');
var rowDate = new Date(arr[0],parseInt(arr[1])-1,arr[2]);
if (!isNaN(rowDate.getTime())) {
if (rowDate >= dateFrom && rowDate <= dateTo) {
row.style.display = 'table-row';
} else {
row.style.display = 'none';
}
}
}
}
Make sure the Date constructor receives valid parsable date formats. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date for more info.
EDIT
Updated answer and corrected time.
I need help to get this working. I have done a script that validate the field "Personalnumber". But i dont know how to link the togheter and get it working.
Can someone help?
//If the form looks weird, i have deleted all the other fields just to get a shorter code.
<script>
function validatePNum(sPNum)
{
var numbers = sPNum.match(/^(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)$/);
var checkSum = 0;
var d = new Date();
if (!isDate(sPNum.substring(0,4),sPNum.substring(4,6),sPNum.substring(6,8))) {
alert("Datumet " + sPNum.substring(0,8) + " är inte korrekt.");
return false;
}
if (numbers == null) { return false; }
var n;
for (var i = 3; i <= 12; i++)
{
n=parseInt(numbers[i]);
if (i % 2 == 0) {
checkSum+=n;
} else {
checkSum+=(n*2)%9+Math.floor(n/9)*9
}
}
if (checkSum%10==0) { return true;}
return false;
}
function getYear(y) { return (y < 1000) ? y + 1900 : y; }
function isDate(year, month, day)
{
month = month - 1; // 0-11 in JavaScript
var tmpDate = new Date(year,month,day);
if ( (getYear(tmpDate.getYear()) == year) &&
(month == tmpDate.getMonth()) &&
(day == tmpDate.getDate()) )
return true;
else
return false;
}
</script>
<form method="post" name="post" action="index.php?site=register">
<tr>
<td class="border_1" align="left">Personnummer:</td>
<td class="border_1"><input id="personalnumber" type="text" name="personalnumber" value="$personalnumber" size="30"/><small> YYYYMMDDXXXX</small></td>
</tr>
<div align="center"><input name="save" type="submit" value="Registera" /></div>
</form>
First of all change the name in your form to something like name="myForm". Then, you can link your JS code with your form by taking the value of the field, ie var x = document.forms["myForm"].value;. Not tested, but this is a way to link your js code with the form in your html.
You Can use jQuery
just add to your form id (like form_id in my example).
$('#form_id').submit(function(){
validatePNum(sPNum)
//do more things
});
I have function that loops every 500ms, and collects date information:
var mlptoday = {};
var timer = setTimeout(today,500);
function today(){
var d = new Date()
mlptoday.date = checkTime(d.getDate()); //output: "27"
mlptoday.year = d.getFullYear(); //output: "2013"
mlptoday.month = checkTime(d.getMonth()+1); //output: "01"
}
function checkTime(i) { if (i<10){i="0" + i} return i }
In a different function, I would like to check if the date the user gives as input is either the same day, or after the given day.
An example input may be: 2013.01.27.
I use this snippet of code to achieve what I want:
var remTime = "2013.01.27"; //user input
var remTimeArray = remTime.split('.') //output: ["2013","01","27"]
if (
!(remTimeArray[0] >= parent.mlptoday.year &&
remTimeArray[1] >= parent.mlptoday.month) ||
!((remTimeArray[1] == parent.mlptoday.month) ? Boolean(remTimeArray[2]*1 >= parent.mlptoday.date) : true)
){
//the input date is in the past
}
As you could probably guess, this does not work. The conditional statement seems to fail me, because if I invert Boolean(...) with an !(...), it will never fire the error, otherwise it always will.
Here's a snippet, where it works at it should:
var mlptoday = {};
var timer = setTimeout(today,500);
function today(){
var d = new Date();
mlptoday.year = d.getFullYear(); //output: "2013"
mlptoday.month = checkTime(d.getMonth()+1); //output: "01"
mlptoday.date = checkTime(d.getDate()); //output: "27"
$('#values').html(JSON.stringify(mlptoday));
}
function checkTime(i) { if (i<10){i="0" + i} return i }
$(document).ready(function(){
$('form').submit(function(e){
e.preventDefault();
var remTime = $('input').val(); //user input
var remTimeArray = remTime.split('.') //output: ["2013","01","27"]
if (
!(remTimeArray[0] >= mlptoday.year &&
remTimeArray[1] >= mlptoday.month) ||
!((remTimeArray[1] == mlptoday.month) ? Boolean(remTimeArray[2]*1 >= mlptoday.date) : true)
){
$('#past').fadeIn('fast').delay(500).fadeOut('fast');
}
})
})
#past { display:none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form>
<input type="text" id="input" required autocomplete="off" placeholder="yyyy.mm.dd" pattern="^(19|20)\d\d[.](0[1-9]|1[012])[.](0[1-9]|[12][0-9]|3[01])$" required="" />
<button>Check</button>
</form>
<pre id="values"></pre>
<span id="past">the input date is in the past</span>
I need a better way to do this, and I don't want to use any date picker plugins.
I would compare the dates as integers to avoid complex logic.
var todayConcat = "" + parent.mlptoday.year + parent.mlptoday.month + parent.mlptoday.date;
var remTimeConcat = remTime.replace(/\./g, "");
if (remTimeConcat < todayConcat) {
//the input time is in the past
}
Just make sure the dates and months always have the leading zero.