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)
Related
I'm trying to make my value to have thousand separators and such, but I don't understand how to use jquery and how it works.
I want to make my value from 1000 to 1,000
and I tried using AutoNumeric like this but failed
var autonumeric = new AutoNumeric.multiple(".form-control");
This is the form where I want to change the value type:
<div class="form-group">
<div class="row">
<div class="col-lg-3">
<label for="total" class="label-control" id="labelsubtotal">Total : </label>
</div>
<div class="col-lg-9">
<input type="text" value="" style="text-align: right;" class="form-control" id="grandTotal" name="grandTotal" disabled>
</div>
</div>
</div>
This is how I import AutoNumeric:
<script src="<?php echo base_url();?>js/autonumeric-next/src/AutoNumeric.js" type="text/javascript"></script>
Basically this is what I want to do :
I want the result format changed into currency format
I succeeded in changing only 1 value, this is what I did:
<script>
$('document').ready(function(){
$(function sum() {
console.log($('.calc'))
var sum = 0.0;
$('.calc').each(function() {
sum += parseInt($(this).text());
});
$("#subTotal").val(sum);
let subTotal = new AutoNumeric("#subTotal");
})();
function calculateSubTotal() {
var subtotal = $("#subTotal").val();
$("#subTotalDiscount").val(subtotal - (Math.round(($("#inputDiscount").val() / 100) * subtotal)));
var subtotal_discount = parseInt($("#subTotalDiscount").val());
$("#subTotalTax").val(Math.round(($("#inputTax").val() / 100) * subtotal_discount));
var subtotal_tax = parseInt($("#subTotalTax").val());
var pph = $("#inputpph").val();
$("#SubTotalpph").val(Math.round(parseInt($("#inputpph").val()*subtotal_discount)));
var subtotal_pph = parseInt($("#SubTotalpph").val());
var grandtotal = subtotal_discount + subtotal_tax + subtotal_pph;
$("#grandTotal").val(grandtotal);
}
})
</script>
I'm lost right now.
Also exists a little bit another way to do it. Do next and look what you'll get(one requirement - you need to give number value only):
JS
$('#grandTotal').on('input',function(){
var number, s_number, f_number;
number = $('#grandTotal').val();
s_number = number.replace(/,/g,'');
f_number = formatNumber(s_number);
console.info(f_number);
$('#grandTotal').val(f_number);
});
function formatNumber(num) {
return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
}
But, if you want just convert value without changing it dynamically then just add this in your attached *.js:
var number, f_number;
number = $('#grandTotal').val();
f_number = formatNumber(number);
console.info(f_number);
$('#grandTotal').val(f_number);
function formatNumber(num) {
return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
}
I want to subtract a user input years from another input years, but so far I had no luck.
I'll create a snippet where you can play.
What I'm trying to do is to make an input field (A) to enter years only. Then after that select any date and subtract it from the input year (A) (date and month are fixed like 31.03.input_year)...
$(document).on('change', '#year_select', function() {
calculate();
});
$(document).on('change', '#new_date', function() {
calculate();
});
function calculate() {
var year_enter = $('#year_select').val();
var current_year = year_enter+'-03-31';
var new_date = $('#new_date').val();
if(year_enter != '') {
//alert(current_year);
}
if(new_date != '') {
//alert(new_date);
var total = new_date - current_year;
$('#answer').val(total);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Enter years (A)</p>
<input type="number" id="year_select" min="0" placeholder="Eg: 2018, 2001">
<br>
<p>Select Date (B)</p>
<input type="date" id="new_date">
<p>(A - B)</p>
<input type="text" readonly id="answer">
I always get NaN value, my subtract method is incorrect I guess. I tried using setDate(), getDate() etc, but I don't understand the logic.
Thanks in advance...
You can use new Date() to type cast them into date in order to do arithmetic
$(document).on('change', '#year_select', function() {
calculate();
});
$(document).on('change', '#new_date', function() {
calculate();
});
function calculate() {
var year_enter = $('#year_select').val();
var current_year = new Date(year_enter + '-03-31');
var new_date = new Date($('#new_date').val());
if (year_enter != '') {
}
if (new_date != '' && year_enter != '') {
if (current_year < new_date) {
$('#answer').val('A must be greater than B');
return;
}
var total = Math.round(Math.abs((current_year.getTime() - new_date.getTime()) / (24*60*60*1000)));
$('#answer').val(total);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Enter years (A)</p>
<input type="number" id="year_select" min="0" placeholder="Eg: 2018, 2001"><span style="opacity: 0.5;"> this currently has fixed -month-day(-03-31) </span>
<br>
<p>Select Date (B)</p>
<input type="date" id="new_date">
<p>(A - B)</p>
<input type="text" readonly id="answer">
Dates can be tricky to handle, but the moment library makes it a lot easier. In my example I take the input of the two fields, parse them into a moment object and calculate their difference in a duration. You can read more on duration in the Moment.js docs.
The code snippet difference is expressed in days. In case you want to change it to months, or years, update the below line.
log(Math.round(duration.as('days')) + 'days');
You can also include several if statements, to check if the difference is a year, display the result in years. If not, and there's a full month, express the result in months and so on.
Here's a working example in days.
$(document).on('change', '#year_select', function() {
calculate();
});
$(document).on('change', '#new_date', function() {
calculate();
});
function calculate() {
var yearSelect = document.querySelector('#year_select').value;
var newDate = document.querySelector('#new_date').value;
var first_date = new window.moment('31-03-' + yearSelect, 'DD-MM-YYYY');
var second_date = new window.moment(newDate, 'YYYY-MM-DD');
if(yearSelect.length !== 4 || newDate === '') {
log('');
return;
}
var duration = window.moment.duration(first_date.diff(second_date));
log(Math.round(duration.as('days')) + 'days');
}
function log(value) {
var answer = document.querySelector('#answer');
answer.value = value;
}
<script src="https://cdn.jsdelivr.net/momentjs/2.10.6/moment-with-locales.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Enter years (A)</p>
<input type="number" id="year_select" min="0" placeholder="Eg: 2018, 2001">
<br>
<p>Select Date (B)</p>
<input type="date" id="new_date">
<p>(A - B)</p>
<input type="text" readonly id="answer">
NOTE: There are a few discussions out there on how to format a date/duration, e.g. 1 year, 2 months, 5 days. Have a look at a possible solution at these discussions if you want something like this.
How can I format time durations exactly using Moment.js?
How do I use format() on a moment.js duration?
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>
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;
I have an input field that asks user to pick a date and if the date is less than 30 days form today it will display some other contents. I am using jQueryUI datapicker and knockout.js for data binding and here is what I have so far JSFiddle but it's not working. What am I missing?
$(document).ready(function() {
$("#datepicker").datepicker();
});
$(document).ready(function() {
var viewModel = function() {
var self = this;
self.request_due_date = ko.observable();
self.request_due_date_rush = ko.observable(false);
self.request_due_date_rush_reason = ko.observable();
self.request_due_date.subscribe(function(dd) {
var cur = new Date(),
rush_date = cur.setDate(cur.getDate() + 30);
if (dd < rush_date) {
self.request_due_date_rush(true);
}
});
};
ko.applyBindings(new viewModel());
});
<div>Due Date:
<input id="datepicker" data-bind="text: request_due_date" type="text" />
</div>
<div data-bind="visible: request_due_date_rush">Reason For Rush:
<input data-bind="text: request_due_date_rush_reason" />
</div>
it's because when you create the datepicker object, the underlying input element gets moved around in the DOM, breaking the binding. Consider writing your own binding handler, like seen here:
jQuery UI datepicker change event not caught by KnockoutJS
You need to bind value, not text.
<input id="datepicker" data-bind="value: request_due_date" type="text" />
Also the value dd is a string and must be parsed to date, for example using moment.js
var days = moment().diff(moment(dd, "MM/DD/YYYY"), "days");
See updated fiddle
Thanks to #MaxBrodin for the insight (to bind value, not text) and this post I found the following solution to be working. Here is also the updated Fiddle
$(document).ready(function() {
$("#datepicker").datepicker();
});
$(document).ready(function() {
var viewModel = function() {
var self = this;
self.request_due_date = ko.observable();
self.request_due_date_rush = ko.observable(false);
self.request_due_date_rush_reason = ko.observable();
self.request_due_date.subscribe(function(dd) {
var date1 = new Date(dd);
var date2 = new Date();
var timeDiff = Math.abs(date2.getTime() - date1.getTime());
var days = Math.ceil(timeDiff / (1000 * 3600 * 24));
self.request_due_date_rush(days < 30);
});
};
ko.applyBindings(new viewModel());
});
<div>Due Date:
<input id="datepicker" data-bind="value: request_due_date" type="text" />
</div>
<div data-bind="visible: request_due_date_rush">Reason For Rush:
<input data-bind="text: request_due_date_rush_reason" />
</div>