Cannot create from/to date range using bootstrap ui - angularjs

I am using Angular UI Bootstrap components in my application.
There are two dates in it. Available Date and ExpireDate. I want the ExpireDate to be always greater than AvailableDate.
var expireMinDate = new Date();
$scope.OpenExpireDate = function() {
$scope.expireDatePopup.opened = true;
var newMinDate = $scope.availableDateOptions.minDate;
$scope.expireDateOptions.minDate = expireMinDate.setDate(newMinDate.getDate() + 1);
};
I tried this code. This is not working. The ExpireDate is not disabled the way I intend. I am not getting the code to disable all the other days. What could be wrong?
Update: Now I am watching the AvailableDate and changing the minDate accordingly.
$scope.$watch('AvailableDate', function() {
var newMinParts = $scope.AvailableDate.toString().split("-");
$scope.expireDateOptions.minDate = new Date(newMinParts[0], newMinParts[1]-1, newMinParts[2]);
});
Updated Fiddle: https://jsfiddle.net/codeandcloud/cpu4euoj/4/
The idea is to update the ExpireDate minDate setting to reflect the change in AvailableDate. Now the minDate setting has completely vanished.

For html part
<div class="container" ng-app="demoApp" ng-controller="demoController">
<div id="demoForm" name="demoForm" ng-form="demoForm" novalidate>
<div class="col-md-4">
<label class="control-label">Available Date</label>
<div class="input-form">
<input type="text" class="form-control" uib-datepicker-popup="{{dateFormat}}" ng-model="AvailableDate" name="availabledate" is-open="availableDatePopup.opened" datepicker-options="availableDateOptions" ng-required="true" data-ng-change="captureChange(AvailableDate)" close-text="Close" ng-click="OpenAvailableDate()"
placeholder="Available Date" />
<label ng-show="showMessages && addJobForm.availabledate.$invalid" class="text-danger">
Available Date is required.
</label>
</div>
</div>
<div class="col-md-4">
<label class="control-label">Expire Date</label>
<div class="input-form">
<input type="text" class="form-control" uib-datepicker-popup="{{dateFormat}}" ng-model="ExpireDate" name="expiredate" is-open="expireDatePopup.opened" datepicker-options="expireDateOptions" ng-required="true" close-text="Close" ng-click="OpenExpireDate()"
placeholder="Expire Date" />
<label ng-show="showMessages && addJobForm.expiredate.$invalid" class="text-danger">
Expire Date is required.
</label>
</div>
</div>
</div>
For JAvascript Part
var demoApp = angular.module('demoApp', ["ui.bootstrap"]);
demoApp.controller("demoController", ["$scope",
function($scope) {
var today = new Date();
$scope.dateFormat = 'yyyy-MM-dd';
$scope.availableDateOptions = {
formatYear: 'yy',
startingDay: 1,
minDate: today,
maxDate: new Date(2030, 5, 22)
};
$scope.expireDateOptions = {
formatYear: 'yy',
startingDay: 1,
minDate: today,
maxDate: new Date(2030, 5, 22)
};
$scope.availableDatePopup = {
opened: false
};
$scope.expireDatePopup = {
opened: false
};
$scope.OpenAvailableDate = function() {
$scope.availableDatePopup.opened = true;
};
$scope.captureChange = function(val){
var expDate = angular.copy(val);
expDate.setDate(expDate.getDate()+1);
$scope.ExpireDate = expDate;
}
var expireMinDate = new Date();
$scope.OpenExpireDate = function() {
$scope.expireDatePopup.opened = true;
var newMinDate = $scope.availableDateOptions.minDate;
if($scope.AvailableDate != undefined){
var ddnew = angular.copy($scope.AvailableDate);
ddnew.setDate(ddnew.getDate()+1);
$scope.expireDateOptions.minDate = ddnew;
}
else{
$scope.expireDateOptions.minDate = today;
}
};
}]);

Related

Date picker validation in angularJS not working

I am trying to implement validations for my date time picker. I have a 'From' date picker and a 'To' datepicker in an Angular partial view. I want the 'From' date picker to display error message if a past date is selected and the 'To' date picker should display error message if the selected date is before the 'From' date. The error messages are supposed to appear on selection of the date.
My HTML is :
<div>
<form id="edit-profile" novalidate name="editReservationForm" autocomplete="off" class="form-horizontal">
<fieldset>
<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"
validator="required" required-error-message="Date is required" valid-method="watch" id="startDate" />
<div class="input-group-addon">
<span class="glyphicon glyphicon-th"></span>
</div>
</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" ng-model="reservation.reservedTill"
validator="required" required-error-message="Date is required" valid-method="checkErr" id="endDate" ng-change='checkErr()' />
<div class="input-group-addon">
<span class="glyphicon glyphicon-th"></span>
</div>
<span>{{errMessage}}</span>
</div> <!-- /controls -->
</div> <!-- /control-group -->
</fieldset>
</form>
</div>
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 () {
if ($scope.editReservationForm.$valid) {
//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.checkErr = function () {
var startDate = new Date($scope.reservation.reservedFrom),
endDate = new date($scope.reservation.reservedTill);
$scope.errMessage = '';
if (startDate < new Date()) {
$scope.errMessage = 'Start Date should be greater than or equal today';
return false;
}
if (new Date(endDate) < new Date()) {
$scope.errMessage = 'End Date should be greater than or equal today';
return false;
}
if (endDate < startDate) {
$scope.errorMsg = "End must be after start";
return false;
}
return true;
};
}]);
I am totally new to Angular and I'm trying to understand it by doing projects. Can anyone have a check and provide a solution?
Thanks in advance...
A different approach without displaying any error message and satisfying selection criteria as mentioned in problem statement
Here is the plunker of working solution bit slightly different from your implementation,I've used bootstrap datepicker for this example which is almost similar to datetimepicker. Hope this will give you an understanding.
In the controller we can control when and what from and to dates should be disabled on their corresponding selection.Using minDate provided by datepicker we can change the min date of To date field to From date's.
By doing this we can eliminate the display of error message and which will also satisfy your selection criteria of From & To dates.
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('DatepickerPopupDemoCtrl', function($scope) {
$scope.datePicker = {};
$scope.start = new Date();
$scope.end = new Date();
$scope.datePicker.minStartDate = new Date();
// $scope.datePicker.maxStartDate = $scope.end;
$scope.datePicker.minEndDate = $scope.start;
// $scope.datePicker.maxEndDate = $scope.end; //fixed date same as $scope.maxStartDate init value
// watcher to watch the "From" date and set the min date for 'To' datepicker
$scope.$watch('start', function(v) {
$scope.datePicker.minEndDate = v;
$scope.dateOptions2.minDate = v;
});
$scope.dateOptions1 = {
//dateDisabled: disabled,
formatYear: 'yyyy',
// maxDate: $scope.datePicker.maxStartDate,
minDate: $scope.datePicker.minStartDate,
startingDay: 1
};
$scope.dateOptions2 = {
//dateDisabled: disabled,
formatYear: 'yyyy',
// maxDate: $scope.datePicker.maxEndDate,
minDate: $scope.datePicker.minEndDate,
startingDay: 1
};
// Disable weekend selection
function disabled(data) {
var date = data.date,
mode = data.mode;
return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6);
}
$scope.open1 = function() {
$scope.popup1.opened = true;
};
$scope.open2 = function() {
$scope.popup2.opened = true;
};
$scope.formats = ['dd.MM.yyyy'];
$scope.format = $scope.formats[0];
$scope.altInputFormats = ['M!/d!/yyyy'];
$scope.popup1 = {
opened: false
};
$scope.popup2 = {
opened: false
};
});
In your HTML you can display like below
<div ng-controller="DatepickerPopupDemoCtrl">
<h5>From Date</h5>
<p class="input-group">
<input type="text"
class="form-control"
uib-datepicker-popup="{{format}}"
ng-model="start"
is-open="popup1.opened"
datepicker-options="dateOptions1"
close-text="Close"
readonly="true" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open1()">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</p>
<hr>
<h5>To Date</h5>
<p class="input-group">
<input type="text"
class="form-control"
uib-datepicker-popup="{{format}}"
ng-model="end"
is-open="popup2.opened"
datepicker-options="dateOptions2"
close-text="Close"
readonly="true"/>
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open2()">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</p>
</div>

Angularjs factory data or object inaccessible directly inside the controller

I have just created an Angular JS factory (below is the code) which returns data for two datepickers (ui.bootstrap's elements) and bind to my html code, but when I am trying to modify the return $scope object by factory inside the controller its not working, I mean I cannot access the $scope.Date1 or $scope.Date2 objects which are available inside the controller (returned from factory).
var MyApp = angular.module("TestApp", ["ui.bootstrap"]);
angular.module('TestApp').factory('FirstFactory', function() {
return {
TwoDates: function(scope) {
scope.clear = function() {
scope.Date1 = null;
scope.Date2 = null;
};
scope.inlineOptions1 = {
customClass: getDayClass,
minDate: new Date(),
// showWeeks: true
};
scope.inlineOptions2 = {
customClass: getDayClass,
minDate: new Date(),
// showWeeks: true
};
scope.dateOptions1 = {
//dateDisabled: disabled,
formatYear: 'yyyy',
maxDate: new Date(2050, 7, 22),
minDate: new Date(),
startingDay: 1
};
scope.dateOptions2 = {
//dateDisabled: disabled,
formatYear: 'yyyy',
maxDate: new Date(2050, 5, 22),
minDate: new Date(),
//minDate: new Date($scope.changeMin()),
startingDay: 1
};
scope.toggleMin = function() {
scope.inlineOptions1.minDate = scope.inlineOptions1.minDate ? null : new Date();
scope.dateOptions1.minDate = scope.inlineOptions1.minDate;
var min2 = new Date();
scope.$watch('Date1', function() {
min2 = scope.Date1;
scope.dateOptions2.minDate = min2;
if (scope.Date1 > scope.Date2) {
// debugger;
scope.Date2 = scope.Date1;
console.log("Yes It's greater");
}
// console.log(min2);
});
scope.$watch('Date2', function() {
if (scope.Date2 < scope.Date1) {
//debugger;
scope.Date1 = scope.Date2;
console.log("Yes It's lesser");
}
// console.log(max1);
});
};
scope.toggleMin();
scope.open1 = function() {
scope.popup1.opened = true;
};
scope.open2 = function() {
scope.popup2.opened = true;
};
scope.popup1 = {
opened: false
};
scope.popup2 = {
opened: false
};
scope.setDate = function(year, month, day) {
scope.Date1 = new Date(year, month, day);
scope.Date2 = new Date(year, month, day);
};
scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd-MM-yyyy', 'shortDate'];
scope.format = scope.formats[2];
scope.altInputFormats = ['M!/d!/yyyy'];
function getDayClass(data) {
var date = data.date,
mode = data.mode;
if (mode === 'day') {
var dayToCheck = new Date(date).setHours(0, 0, 0, 0);
for (var i = 0; i < scope.events.length; i++) {
var currentDay = new Date(scope.events[i].date).setHours(0, 0, 0, 0);
if (dayToCheck === currentDay) {
return scope.events[i].status;
}
}
}
return '';
}
}
};
});
angular.module('TestApp').controller('StartDate', function($scope, $log, FirstFactory) {
//debugger;
FirstFactory.TwoDates($scope);
//or
console.log($scope.Date1);
});
<fieldset>
<form name="MeForm" novalidate>
<div ng-controller="StartDate">
<div class="row">
<div class="col-md-3">
<div>
<p class="input-group">
<input type="text" name="fdate" class="form-control" uib-datepicker-popup="{{format}}" ng-model="Date1" is-open="popup1.opened" datepicker-options="dateOptions1" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
<p class="error validationerror" ng-show="MeForm.fdate.$invalid && MeForm.fdate.$touched">First date is required</p>
</p>
</div>
<input type="text" [ng-value="Date1" ] />#*{{Date1 | date: 'dd-MM-yyyy'}}*#
<div>
<p class="input-group">
<input type="text" name="ldate" class="form-control" uib-datepicker-popup="{{format}}" ng-model="Date2" is-open="popup2.opened" datepicker-options="dateOptions2" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open2()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
<p class="error validationerror" ng-show="MeForm.ldate.$invalid && MeForm.ldate.$touched">Last date is required</p>
</p>
</div>
#*{{Date2 | date: 'dd-MM-yyyy'}}*#
</div>
</div>
</div>
<div>
<input type="text" name="firstname" ng-required="true" ng-model="user.firstname" placeholder="Enter your first name" class="form-control" />
<p class="error validationerror" ng-show="MeForm.firstname.$invalid && MeForm.firstname.$touched">You must fill out your first name</p>
<br />
<input type="text" name="lastname" ng-required="true" ng-model="user.lastname" placeholder="Enter your first name" class="form-control" />
<p class="error validationerror" ng-show="MeForm.lastname.$invalid && MeForm.lastname.$touched">You must fill out your last name</p>
<br />
<button type="submit" class="btn submitbtn">Submit</button>
</div>
</form>
</fieldset>
You constructed your factory return statement very oddly. Instead of this:
angular.module('TestApp').factory('FirstFactory', function() {
return {
TwoDates: function(scope) {
scope.example = function() {
//logic
}
//etc functions
}
}
}
Try it like this instead.
angular.module('TestApp').factory('FirstFactory', function() {
var Date1 = 0;
var Date2 = 0;
TwoDates.example = function(){
//logic on Date1 or Date2
}
//TwoDates.exampleFunction = function(){....
return TwoDates; //Important!
}
Notice that the factory's purpose is to return an object that contains all of your logic and variables.
This way you'll be able to use the Date1 and Date2 variables from within the factory and in any controllers that you use the factory in using factoryInstance.getDate1.
In the end your code (the very basics at least) will look like this
var MyApp = angular.module("TestApp", ["ui.bootstrap"]);
angular.module('TestApp').factory('FirstFactory', function() {
var Date1 = 0;
var Date2 = 0;
TwoDates.incrDate1 = function(){
Date1 += 1;
}
TwoDates.getDate1 = function(){
return Date1;
}
return TwoDates;
}
angular.module('TestApp').controller('StartDate', function($scope, FirstFactory) {
//get *function* that returns variables from Factory
//notice that I don't use FF.getDate1(), but instead pass the function without invoking it
$scope.getDate1 = FirstFactory.getDate1; //<-- no ()
console.log($scope.getDate1); // 0
FirstFactory.incrDate1(); // calls Factory method, uses Date1 variable
console.log($scope.getDate1); // 1
//you can also add other factory functions to your scope so you can use them in the html
$scope.incrDate1 = FirstFactory.incrDate1();
});
Here's another stackoverflow question that might help you out.

Angularjs UI bootstrap Datepicker

I am using Angularjs datepicker in my application. I want to display selected date in UI. It should display "Selected Date:dd/MM/yyyy" which is working correctly. But If I select today's date it should display "Today:dd/MM/yyyy".
But for today's date also it is showing "Selected Date:dd/MM/yyy". Can anyone please help me .
my html code.
<div ng-controller="DatepickerDemoCtrl">
Selected date is: {{dt | date:'dd/MM/yyyy' }}
<div >
<div >
<div>
<button type="button" class="btn btn-default"
datepicker-popup="{{format}}" ng-model="dt"
is-open="status.opened" min-date="minDate" show-weeks="false" show-button-bar="false"
max-date="maxDate" datepicker-options="dateOptions"
date-disabled="disabled(date, mode)" ng-required="true"
close-text="Close" ng-click="open($event)">
<img src="calendar.png" /></button>
</div>
</div>
JS code
var app= angular.module('myApp', ['ui.bootstrap']);
app.controller('DatepickerDemoCtrl', function ($scope) {
$scope.today = function() {
$scope.dt = new Date();
};
$scope.today();
$scope.refresh = function(){
$scope.dt = new Date();
};
$scope.maxDate = new Date(new Date().setDate(new Date().getDate()));
$scope.minDate = new Date(new Date().setDate(new Date().getDate()-7));
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.status.opened = true;
};
$scope.setDate = function(year, month, day) {
$scope.dt = new Date(year, month, day);
};
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
$scope.status = {
opened: false
};
});

Using angularjs ui bootstrap datepicker and timepicker together

I'm trying to add the value of my ui.bootstrap timepicker to the date in my input (text) like so:
Not sure what my code is missing to accomplish that.
Code taken from angularjs.ui.bootstrap
Here's my plunker
Thanks
html
<div ng-app="ui.bootstrap.demo">
<div ng-controller="DatepickerDemoCtrl">
<div class="form-group">
<div class="col-md-6">
<label for="appointment_start">Appointment datetime start:</label>
<p class="input-group">
<input type="date" id="appointment_start" name="appointment_start" class="form-control" readonly datepicker-popup ng-model="dt" is-open="status.opened" max-date="'2020-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true"
close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
<timepicker ng-model="dt" hour-step="1" minute-step="15" show-meridian="true">
</timepicker>
</div>
</div><!-- ng-controller -->
</div><!-- ng-app -->
js
angular
.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap'])
.controller('DatepickerDemoCtrl', function ($scope) {
$scope.today = function() {
$scope.dt = new Date();
};
$scope.today();
$scope.clear = function () {
$scope.dt = null;
};
// Disable weekend selection
$scope.enabled = function(date, mode) {
return ( mode === 'day' && ( date.getDay() === 0 || date.getDay() === 6 ) );
};
$scope.open = function($event) {
$scope.status.opened = true;
};
$scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
$scope.format = $scope.formats[0];
$scope.status = {
opened: false
};
var tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
var afterTomorrow = new Date();
afterTomorrow.setDate(tomorrow.getDate() + 2);
$scope.events =
[
{
date: tomorrow,
status: 'full'
},
{
date: afterTomorrow,
status: 'partially'
}
];
$scope.getDayClass = function(date, mode) {
if (mode === 'day') {
var dayToCheck = new Date(date).setHours(0,0,0,0);
for (var i=0;i<$scope.events.length;i++){
var currentDay = new Date($scope.events[i].date).setHours(0,0,0,0);
if (dayToCheck === currentDay) {
return $scope.events[i].status;
}
}
}
return '';
};
});
The angular-ui datepicker needs type="text" on the input field
<input type="text" .../>
and the proper format to show the formatted date and time from the timepicker. I adjusted the first format to 'dd-MMMM-yyyy hh:mm:ss' in the controller.
$scope.formats = ['dd-MMMM-yyyy hh:mm:ss', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
$scope.format = $scope.formats[0];
Here is a working plunker.

Load JSON objects using value from Angular UI datepicker

I want to load JSON objects only if the date property of the objects event.node.date matches the date selected by the user from the Angular UI datepicker ng-model="dt". I'd be grateful for any help.
Here's my stuff as it stands, loading all the JSON objects regardless of date and with the datepicker not actually connected to the get request in any way:
JS:
var weekEventsController = function($scope, $http){
$http.get('/json/next7days').success(function(result){
$scope.weekEvents = (function(){
return result.nodes;
})();
});
$scope.today = function() {
$scope.dt = new Date();
};
$scope.today();
$scope.clear = function () {
$scope.dt = null;
};
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
$scope.format = 'dd MMMM yyyy';
};
HTML:
<div class="col-md-8 col-sm-8" ng-controller="weekEventsController">
<h2 datepicker-popup="{{format}}" ng-model="dt" is-open="opened" min-date="{{today}}" max-date="'2016-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close">
{{dt | date:'dd MMMM yyyy' }}
<i class="fa fa-calendar-o" ng-click="open($event)"></i>
</h2>
<div class="mainEventItem" ng-repeat="event in weekEvents">
<main-item-container>
<div class="mainItemDetails">
<h2 class="eventTitle">{{event.node.title}}</h2>
<p class="eventDate">{{event.node.date | date: 'EEEE'}} / {{event.node.field_time}} / {{event.node.venue}}</p>
</div>
</main-item-container>
</div>
</div>

Resources