Angular UI Bootstrap datepicker in modal only working on first click - angularjs

The date picker seems to be only working on the first click and then after that it won't pop up. I am guessing it has something to do with some crossed variable or function definitions, but I can't figure out how to fix it.
Here is the code:
http://plnkr.co/edit/ridTspMBHE1iphrSobQr?p=preview
HTML
<div ng-controller="ModalDemoCtrl">
<button class="btn btn-info" ng-click="open_modal()">Edit</button>
<script type="text/ng-template" id="notificationInput.html">
<div class="modal-header">
<h3 class="modal-title">My Modal</h3>
</div>
<div class="modal-body">
<form role="form">
<div class="form-group">
<label for="n_title">Title</label>
<input type="text" class="form-control" id="n_title" value="{{selectedNotification.title}}">
</div>
<div class="form-group">
<label for="n_release">Release</label>
<p class="input-group">
<input type="text" id="n_release" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="opened" min-date="minDate" max-date="'2015-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>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</script>
</div>
Javascript
angular.module('plunker', ['ui.bootstrap']);
var ModalDemoCtrl = function ($scope, $modal) {
$scope.open_modal = function(notification) {
$scope.selectedNotification = notification;
var modalInstance = $modal.open({
templateUrl: 'notificationInput.html',
controller: ModalInstanceCtrl,
scope: $scope
});
};
};
var ModalInstanceCtrl = function ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.today = function() {
$scope.dt = new Date();
};
$scope.today();
$scope.clear = function () {
$scope.dt = null;
};
// Disable weekend selection
$scope.disabled = function(date, mode) {
return ( mode === 'day' && ( date.getDay() === 0 || date.getDay() === 6 ) );
};
$scope.toggleMin = function() {
$scope.minDate = $scope.minDate ? null : new Date();
};
$scope.toggleMin();
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
$scope.initDate = new Date('2016-15-20');
$scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
$scope.format = $scope.formats[0];
};

As you are using it inside modal there is scope issue. You just need to use $parent.opened instead opened.
Modified HTML
<input type="text" id="n_release" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="$parent.opened" min-date="minDate" max-date="'2015-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
Working DEMO

This has worked for me:
In html replace is-open="opened" by is-open="field.opened"
and the same in the controller, replace
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
by
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.field.opened = true;
};

Related

extract lengthy similar View components into directive

I know directive can generate HTML DOM
is It possible to have different controllers for each directive?
For example I have two similar datepickers, each has different controller
I wonder how to use directive to simplify my code
The differences between the two similar components are ng-model and ng-controller
VIEW
<div class="form-group" ng-controller="FlightSkuStartDatepickerCtrl">
<label class="col-sm-2 control-label"> {{ I18n.t("choose_start_date") }} </label>
<div class="col-sm-10" ng-click="open($event)">
<input type="text" class="form-control ng-pristine ng-untouched ng-valid ng-isolate-scope ng-valid-date ng-valid-required" datepicker-popup="yyyy/MM/dd" is-open="opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" required="required" aria-required="false" aria-invalid="false" ng-model="form.start_date"></input>
</div>
</div>
<div class="form-group" ng-controller="FlightSkuEndDatepickerCtrl">
<label class="col-sm-2 control-label"> {{ I18n.t("choose_end_date") }} </label>
<div class="col-sm-10" ng-click="open($event)">
<input type="text" class="form-control ng-pristine ng-untouched ng-valid ng-isolate-scope ng-valid-date ng-valid-required" datepicker-popup="yyyy/MM/dd" is-open="opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" required="required" aria-required="false" aria-invalid="false" ng-model="form.end_date"></input>
</div>
</div>
Controller
app.controller('FlightSkuStartDatepickerCtrl', ['$scope',
function($scope) {
// Disable weekend selection
$scope.disabled = function(date, mode) {
return (mode === 'day' && (date.getDay() === 0 || date.getDay() === 6));
};
$scope.toggleMin = function() {
$scope.minDate = $scope.minDate ? null : new Date();
};
$scope.toggleMin();
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1,
class: 'datepicker'
};
$scope.formats = ['YYYY/MM/DD'];
$scope.format = $scope.formats[0];
}
]);
app.controller('FlightSkuEndDatepickerCtrl', ['$scope',
function($scope) {
// Disable weekend selection
$scope.disabled = function(date, mode) {
return (mode === 'day' && (date.getDay() === 0 || date.getDay() === 6));
};
$scope.toggleMin = function() {
$scope.minDate = $scope.minDate ? null : new Date();
};
$scope.toggleMin();
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1,
class: 'datepicker'
};
$scope.formats = ['YYYY/MM/DD'];
$scope.format = $scope.formats[0];
}
]);

angular ui-bootstrap datepicker mindate not validated when typed in

I have a form with a ui-bootstrap datepicker. I want to prevent the date from being in the past.
I set the min-date setting on the directive to a new Date() as shown below. This correctly prevents selection of dates in the past when using the popup, however I can still type in a date in the past and this validates OK.
How can I enforce min-date validation on dates that are typed in?
Plunkr: https://plnkr.co/edit/EHO1BG8BspNMvsoKT30l?p=preview
Html:
<div class="input-group">
<input type="text"
class="form-control"
uib-datepicker-popup="{{format}}"
ng-model="dt"
is-open="popup1.opened"
min-date="minDate"
datepicker-options="dateOptions"
ng-required="true"
close-text="Close"
alt-input-formats="altInputFormats"
name="dt"/>
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open1()">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</div>
JS:
app.controller('MainCtrl', function($scope) {
$scope.dt = new Date();
$scope.minDate = new Date();
$scope.format = "dd/MM/yyyy";
$scope.altInputFormats = ['d!/M!/yyyy'];
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
$scope.popup1 = {
opened: false
};
$scope.open1 = function() {
$scope.popup1.opened = true;
};
});
This should work correctly, I have added changeHandler function in your controller and called it on ng-change of input.
Html:
<div class="input-group">
<input type="text"
class="form-control"
uib-datepicker-popup="{{format}}"
ng-model="dt"
is-open="popup1.opened"
min-date="minDate"
datepicker-options="dateOptions"
ng-required="true"
close-text="Close"
alt-input-formats="altInputFormats"
ng-change="changeHandler()"
name="dt"/>
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open1()">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</div>
JS:
app.controller('MainCtrl', function($scope) {
$scope.dt = new Date();
$scope.minDate = new Date();
$scope.format = "dd/MM/yyyy";
$scope.altInputFormats = ['d!/M!/yyyy'];
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
$scope.popup1 = {
opened: false
};
$scope.changeHandler = function () {
$scope.dateForm.dt.$setValidity('$valid', $scope.dt.getTime() >= $scope.minDate.getTime());
}
$scope.open1 = function() {
$scope.popup1.opened = true;
};
});

Datepicker in Angular ui modal not opening

I have a datepicker within a form in my modal. The datepicker is not opening no matter what I try. My code is :
//In my parent controller - Called on button click
$scope.openModal = function(indx){
var modalInstance = $modal.open({
animation:true,
templateUrl:'myModal.html',
controller: 'MyModalController'
});
};
//In MyModalController
$scope.open = function(){
$scope.opened = true;
console.log('Opened is : ' + $scope.opened);
};
//Modal view file myModal.html
<input type="text" class="form-control" datepicker-popup="dd.MMMM.yyyy" ng-model="obj.startDate" is-open="$parent.opened" min-date="minDate" max-date="'2015-06-22'" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open(evt)">Close</button>
</span>
This question has been asked before, but the solutions given are not working for me. I have already tried everything suggested here:
ui.bootstrap.datepicker is-open not working in modal
https://github.com/angular-ui/bootstrap/issues/2307
Add $event.preventDefault() and $event.stopPropagation() to your open function in your controller and make sure to pass the $event to the open function in the ng-click:
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
and in your view:
<button type="button" class="btn btn-default" ng-click="open($event)">Close</button>
Run the code snippet to see a working demo:
var app = angular.module('demo', ['ui.bootstrap', 'ngAnimate']);
app.controller('MainCtrl', ['$scope', '$modal', function($scope, $modal){
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl'
});
};
}]);
app.controller('ModalInstanceCtrl', ['$scope', '$modalInstance', function ($scope, $modalInstance) {
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]);
#import url("//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css");
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.0.js"></script>
<div ng-app="demo">
<div ng-controller="MainCtrl" class="container">
<button class="btn btn-default" ng-click="open()">Open Modal</button>
</div>
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Modal with a DatePicker</h3>
</div>
<div class="modal-body">
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="shortDate" ng-model="dt" is-open="opened" />
<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>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="cancel()">Cancel</button>
</div>
</script>
</div>

how to work with 2 datepicker widgets

I have two datepickers, one representing start date and another the end date.
I am using angular-ui.
How to make each one to function independently.
EDIT:
And also how to make the 2 datepickers to appear on the same line
Here is plunkr demo
HTML code
<body ng-controller="DatepickerDemoCtrl">
<br><br><br>
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt1" is-open="opened" min-date="minDate" max-date="'2015-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>
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt1" is-open="opened" min-date="minDate" max-date="'2015-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>
<script type="text/javascript" src="bootstrap-select.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
Thanks in advance
Demo: http://plnkr.co/edit/rGJndx1sXK9u8WCXSMFS?p=preview
JS:
angular.module("myApp", ['ngAnimate', 'ui.bootstrap'])
.controller('DatepickerDemoCtrl', function($scope) {
$scope.today = function() {
$scope.dt1 = new Date();
$scope.dt2 = new Date();
};
$scope.today();
$scope.clear = function() {
$scope.dt1 = null;
$scope.dt2 = null;
};
// Disable weekend selection
$scope.disabled = function(date, mode) {
return (mode === 'day' && (date.getDay() === 0 || date.getDay() === 6));
};
$scope.toggleMin = function() {
$scope.minDate = $scope.minDate ? null : new Date();
};
$scope.toggleMin();
$scope.open1 = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened1 = true;
};
$scope.open2 = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened2 = true;
};
$scope.dateOptions = {
formatYear: 'yy',
startingDay: 1
};
$scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
$scope.format = $scope.formats[0];
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 '';
};
})
.controller("mainctrl", function($scope) {
$scope.courses = [{
"name": "Java",
"level": "I"
}, {
"name": "Python",
"level": "I"
}, {
"name": "Nodejs",
"level": "A"
}];
$scope.caller = function() {
console.log($scope.inputvalue);
};
})
.filter('inArray', function($filter) {
return function(list, arrayFilter, element) {
return $filter("filter")(list, function(listItem) {
return !arrayFilter || arrayFilter.length == 0 || arrayFilter.indexOf(listItem[element]) != -1;
});
};
});
HTML:
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt1" is-open="opened1" min-date="minDate" max-date="'2015-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="open1($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt2" is-open="opened2" min-date="minDate" max-date="'2015-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="open2($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
I am not sure if this is good way to do but I did it in this way. May be someone can correct me on this.
basically you just need to seperate the scope variable, that opens both datepickers.
scope.openFirst = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.openedFirst = true;
};
You could use the same function for both datepickers too and add an argument to the function.
http://plnkr.co/edit/df0GQfnh4g1Os3DwcK0V?p=preview
This is very rudimentary but can give you the right idea and works.
just elaborating on K K's comment
Use different is-open attribute and then pass the attribute in through the ng-click function.Also use different ng-models
<input type="text" datepicker-popup="dd-MMMM-yyyy" ng-model="dt1" is-open="opened1" min="minDate" max="'2015-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true"/>
<button class="btn" ng-click="open($event,'opened1')"><span class="glyphicon glyphicon-calendar"></span></button>
inside controller add the passing argument
$scope.open = function($event,opened) {
$event.preventDefault();
$event.stopPropagation();
$scope[opened] = true;
};

Angular bootstrap.ui datepicker not popup

i'm trying to use angularjs date picker on my project as but seems to be functionality has been broken when i'm integrating date picker to my project
<div class="input-group">
<div class="input-group ui-datepicker">
<input type="text"
class="form-control"
datepicker-popup="yyyy/MM/dd"
ng-model="dt"
is-open="opened"
max="'2015-06-22'"
datepicker-options="dateOptions"
date-disabled="disabled(date, mode)"
ng-required="true"
close-text="Close">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
controller
$scope.dt = new Date();
$scope.open = function ($event) {
$event.preventDefault();
$event.stopPropagation();
return $scope.opened = true;
};
$scope.dateOptions = {
'year-format': "'yy'",
'starting-day': 1
};
$scope.disabled = function (date, mode) {
return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6);
};
what am'i missing there?
thanks
here is the plunkr
You just need to add ng-click="open($event)" to an element, the span for example, and it will work.
http://plnkr.co/edit/bNNrFaeRl6iqFPfa3FMW?p=preview

Resources