Angular JS datepicker doesn't update model - javascript

I'm trying to filter a table using a daterange, but can't get the model to update so it doesn't know what date I picked.
This is the HTML for the datepicker popup:
<label>From:</label>
<p class="input-group" style="width:200px">
<input type="text" class="form-control" uib-datepicker-popup = "{{format}}" ng-model="dt" is-open="status.opened"
min-date="minDate" max-date="maxDate" 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>
The JS code in my controller:
(function ()
{
'use strict';
angular.module('aml-tech-dashboard.successful-emails').controller('datepickerController', function ($scope) {
$scope.dt = '';
$scope.status = {
opened: false
};
$scope.format = "yyyy-MM-dd"
$scope.minDate = new Date();
$scope.dateOptions = {
//formatYear: 'yy',
startingDay: 1
};
$scope.open = function ($event) {
$scope.status.opened = true;
};
});
})();
Table:
<tr ng-repeat = 'file in files | startFrom: dt'>

Your tr element is wrong. It should look like this:
<tr ng-repeat="file in files | startFrom: dt"></tr>
You also have a mistake in the uib-datepicker-popup directive. It should look like this:
uib-datepicker-popup="{{format}}"
This is assuming you have defined the startFrom filter elsewhere in your module, as it is not a built-in Angular filter.

try this:
$scope.dt = new Date();
and make sure that the controller is invoked when the view render.

Related

problems in filter in angularjs

i have a problems in my filter , i explain you, when my program start , i initiaze the table(ng repeat)
but
first
in console log () When I initialize the first time it puts me "item undifined" and then it returns in directly in the filter "myfilter" and it shows me the object,
i don't uderstand why i have "items undifined"
And I would like it to do it all at once and the second problem is to link to the first problem, when I press a datepicker field it makes me 2 alert so it calls twice the filter
this is my filter code
routeAppControllers.filter("myfilter", function($filter) {
return function(items, from, to) {
const testFrom = Date.parse(from);
const testTo = Date.parse(to);
if (!testFrom){
// console.log('Not valid');
from = moment();
}
if (!testTo){
to = moment('2500-01-01');
}
const valids = items.reduce((acc,val) => {
var st = val.DATE_AGENDA;
// alert(val.DATE_AGENDA);
/*
var res = st.substring(0, 10);
var res = res.split("-");
var res1= res[2]+'-'+res[1]+'-'+res[0];
alert(res);
var dt = new Date(res1);
*/
const date = moment(val.DATE_AGENDA);
if(date.isSameOrAfter(from) && date.isSameOrBefore(to))
acc.push(val)
return acc;
},[]);
return valids;
};
});
this is my 2 inputs
<input type="text" placeholder="Date debut" class="form-control" ng-click="open1()" uib-datepicker-popup ng-model="startDate" show-button-bar="false" is-open="popup1.opened" datepicker-options="dateOptions" ng-change="filter()" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
<input type="text" placeholder="Date fin" class="form-control" ng-click="open2()" uib-datepicker-popup ng-model="endDate" show-button-bar="false" is-open="popup2.opened" datepicker-options="dateOptions" ng-change="filter()" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open2()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
and this is my ng-repeat
<tr ng-repeat="data in filtered = (myData | filter:search | orderBy : predicate :reverse | myfilter: startDate: endDate) | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit">
and i make i plunker for more help
http://plnkr.co/edit/6RuUjkON4HaXE3EHg7bn?p=preview
if somenone can help me
thanks in advance

TypeError: Undefined on module pattern of object instances

This is kind of a follow-up to this question:
How to have at least two datepickers of ui-bootstrap on a single page?
It does a great job of having an elegant way to handle multiple instances of angular bootstrap datepicker elements on the same view/page. At least it appears to... I get the following error.
TypeError: Cannot set property 'BeginDate' of undefined
This occurs when I click to attempt to open the date dialog. It happens on the line below, which you can see in the code sample below that. The instances object is undefined.
method.instances[instance] = true;
From what I can tell, my code and the example in the other question are nearly identical.
Example controller code:
$scope.datePicker = (function() {
var method = {};
var instances = [];
method.open = function ($event, instance) {
$event.preventDefault();
$event.stopPropagation();
method.instances[instance] = true;
};
method.minDate = new Date();
method.maxDate = new Date(2023, 12, 24);
method.options = {
formatYear: "yyyy",
startingDay: 1
};
method.format = "dd-MM-yyyy";
return method;
}());
Example element code:
<div class="form-group">
<label for="beginDate" class="col-md-5">Begin Date</label>
<input type="text" name="beginDate" ng-model="codeCamp.BeginDate" datepicker-popup="{{datePicker.format}}" min-date="datePicker.minDate" max-date="datePicker.maxDate" datepicker-options="datePicker.options" is-open="datePicker.instances['BeginDate']" ng-required="true" close-text="Close" class="form-control" required />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="datePicker.open($event, 'BeginDate')"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
<div class="form-group">
<label for="endDate" class="col-md-5">End Date</label>
<input type="text" name="endDate" ng-model="codeCamp.EndDate" datepicker-popup="{{datePicker.format}}" min-date="datePicker.minDate" max-date="datePicker.maxDate" datepicker-options="datePicker.options" is-open="datePicker.instances['EndDate']" ng-required="true" close-text="Close" class="form-control" required />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="datePicker.open($event, 'EndDate')"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
Have you tried to create the instances array in the method object?
Instead of this:
var method = {};
var instances = [];
Use this:
var method = {};
method.instances = [];
Let me know!

disable weekend dates on angular bootstrap datepicker using custom directive

I'm using Angular bootstrap datapicker plugin in my angular app.
I've written a custom directive for the date pickers in my app. And i want to disable the weekends in the date picker at certain places. I've given the functions that disables the weekend dates inside the directive itself.
The function to disable the weekend dates works fine when it is not used inside the directive.
My custom directive:
app.directive('datePic', function(){
return {
restrict: 'E',
scope: {
control: "=ngModel",
min: "=minDate",
max: "=maxDate",
disable: "&dateDisabled"
},
template: '<div class="col-sm-6"><div class="input-group"><input type="text" class="form-control" datepicker-popup is-open="opened1" ng-model="control" min-date="min" max-date="max" date-disabled="disable" close-text="Close" /><span class="input-group-btn"><button type="button" id="btn2" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button></span></div></div>',
link: function(scope, elem, attrs){
scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
scope.opened1 = true;
};
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();
}
}
})
HTML:
<div class="form-group has-feedback">
<label for="inputEmail3" class="col-sm-3 control-label"><span>*</span>From :</label>
<date-pic ng-model="data.leaveFromDate" min-date="minDate" max-date="maxdate" date-disabled="disabled(date, mode)"></date-pic>
</div>
<div class="form-group has-feedback">
<label for="inputEmail3" class="col-sm-3 control-label"><span>*</span>To :</label>
<date-pic ng-model="data.leaveToDate" min-date="data.leaveFromDate" max-date="data.leaveToDate" date-disabled="disabled(date, mode)"></date-pic>
</div>
I dont know how to pass date-disabled="disabled(date, mode)" into the directive so that it is possible to disable weekend dates dynamically.
I have assigned date-disabled inside the directive as disable: "&dateDisabled" and used it in the template as date-disabled="disable".
Any suggestions or guidance much appreciated.
Thank you in advance.
Since you are defining your disabled function within your custom datePic directive, there is no need to pass it in to your custom directive at all.
You do need to make a change to the template within your directive. It needs to reference the disabled function that you have defined in the link function of your custom directive. So it would look like this: date-disabled="disabled(date, mode)".
If you want to only disable weekends sometimes, I would pass in a parameter to your custom directive to control this.
Working Jsfiddle here with the 3 changes above.
If you specifically want to pass in a custom disabled function to your directive, here is a Jsfiddle that does that. Note that the disabled function is now defined outside the directive in a controller.
<script language="javascript" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.14.3.js"></script>
enter code here
<div ng-app="myApp" ng-controller="myCntrl">
From Date:
<input type="text" uib-datepicker-popup="{{dateformat}}" min-date="mindate" ng-model="dt" is-open="showdp"
date-disabled="disabled(date, mode)" />
<span>
<button type="button" class="btn btn-default" ng-click="showcalendar($event)">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</div>
<script language="javascript">
angular.module('myApp', ['ngAnimate', 'ui.bootstrap']);
angular.module('myApp').controller('myCntrl', function ($scope) {
$scope.today = function () {
$scope.dt = new Date();
};
$scope.mindate = new Date();
$scope.dateformat="dd/MM/yyyy";
$scope.today();
$scope.showcalendar = function ($event) {
$scope.showdp = true;
};
$scope.showdp = false;
$scope.disabled = function (date, mode) {
return (mode === 'day' && (date.getDay() === 0 || date.getDay() === 6));
};
});
</script>
</form>

Using datepicker on more than one input

I have following two input fields that use datepicker.
<div class="row">
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="opened" min="minDate" max="'2015-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
<div>
<div class="row">
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt2" is-open="opened" min="minDate" max="'2015-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
The controller code is
angular.module('plunker', ['ui.bootstrap']);
var DatepickerDemoCtrl = function ($scope) {
$scope.today = function() {
$scope.dt = new Date();
};
$scope.today();
$scope.showWeeks = true;
$scope.toggleWeeks = function () {
$scope.showWeeks = ! $scope.showWeeks;
};
$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 = {
'year-format': "'yy'",
'starting-day': 1
};
$scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'shortDate'];
$scope.format = $scope.formats[0];
};
Problem is whenever I click any button both datepicker calenders pop up. Here is the plunker for it
http://plnkr.co/edit/hcLogY0SPsFzewcCt0xh?p=preview
Please let me know how to fix it. Thanks
You can split your code with 2 ng-controllers.
http://plnkr.co/edit/Cp7ZlWl8Ee8TCAOnfxv2?p=preview

How to usemultiple Angular UI Bootstrap Datepicker in single form?

I have a form where there is a need for me to have 2 or more date fields for different things. I tried the Angular UI Bootstrap which works fine when I have only 1 date field in the form. But it stops working if I have multiple date fields and I dont know the easier method to get this to work.
This is my HTML sample:
<label>First Date</label>
<div class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" name="dt" ng-model="formData.dt" is-open="opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
<label>Second Date</label>
<div class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" name="dtSecond" ng-model="formData.dtSecond" is-open="opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
My JS is:
myApp.controller('DatePickrCntrl', function ($scope) {
$scope.today = function() {
$scope.formData.dt = new Date();
};
$scope.today();
$scope.showWeeks = true;
$scope.toggleWeeks = function () {
$scope.showWeeks = ! $scope.showWeeks;
};
$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 = {
'year-format': "'yy'",
'starting-day': 1
};
$scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'shortDate'];
$scope.format = $scope.formats[0];
});
I implemented based on the sample here. The problem I have here is:
1) When one of the date field is clicked, the pop-up datepicker is messed up and seems to show 2 datepicker in 1.
2) When I remove is-open="opened" attribute, the pop-up window seems to work fine. But without is-open="opened", the ng-click="open($event) for the button doesnt work.
3) Since each of the date fields have different ng-models, I am unable to set default dates for any date fields except for the first one with ng-model="formData.dt"
The only long way to resolve this that I can think of is to separate the controller for each date field.
I would like to know how others implement multiple date fields in 1 form itself when using Angular UI Bootstrap.
I have 30 in one form one controller no problem. use the same concept if you need it on ng-repeat.
<label>First Date</label>
<div class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}"
name="dt" ng-model="formData.dt" is-open="datepickers.dt"
datepicker-options="dateOptions" ng-required="true"
close-text="Close" />
<span class="input-group-btn">
<button class="btn btn-default" ng-click="open($event,'dt')">
<i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
<label>Second Date</label>
<div class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}"
name="dtSecond" ng-model="formData.dtSecond"
is-open="datepickers.dtSecond" datepicker-options="dateOptions"
ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button class="btn btn-default" ng-click="open($event,'dtSecond')">
<i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
myApp.controller('DatePickrCntrl', function ($scope) {
$scope.datepickers = {
dt: false,
dtSecond: false
}
$scope.today = function() {
$scope.formData.dt = new Date();
// ***** Q1 *****
$scope.formData.dtSecond = new Date();
};
$scope.today();
$scope.showWeeks = true;
$scope.toggleWeeks = function () {
$scope.showWeeks = ! $scope.showWeeks;
};
$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, which) {
$event.preventDefault();
$event.stopPropagation();
$scope.datepickers[which]= true;
};
$scope.dateOptions = {
'year-format': "'yy'",
'starting-day': 1
};
$scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'shortDate'];
$scope.format = $scope.formats[0];
});
// ***** Q2 ***** somemodel can be just an array [1,2,3,4,5]
<div ng-repeat="o in somemodel">
<label>Date Label</label>
<div class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}"
name="dt{{o}}" ng-model="datepickers.data[o]"
is-open="datepickers.isopen[o]" datepicker-options="datepickers.option"
ng-required="true" close-text="Close" />
<span class="input-group-btn">
<button class="btn btn-default" ng-click="open($event,o)">
<i class="glyphicon glyphicon-calendar"></i></button>
</span>
</div>
</div>
myApp.controller('DatePickrCntrl', function ($scope) {
$scope.datepickers = {
data: {},
options: {
'year-format': "'yy'",
'starting-day': 1
},
isopen: {}
}
$http.get("get/data/for/some/model", function(result) {
$scope.somemodel = result;
for (var i = 0; i < result.length; i++) {
$scope.datepickers.isopen[result] = false;
$scope.datepickers.data[result] = new Date(); //set default date.
}
});
// fill in rest of the function
});
Simpler Solution. Requires only modding the HTML and can be used in a ng-repeat if you like. Just be creative with what you name the opened
Stick this in your Controller:
$scope.calendar = {
opened: {},
dateFormat: 'MM/dd/yyyy',
dateOptions: {},
open: function($event, which) {
$event.preventDefault();
$event.stopPropagation();
$scope.calendar.opened[which] = true;
}
};
HTML:
<div class="form-group row">
<div class="col-lg-6">
<label for="formDOB">Date of Birth</label>
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="{{calendar.dateFormat}}" ng-model="record.birthDate" is-open="calendar.opened.dob" datepicker-options="calendar.dateOptions" close-text="Close" placeholder="Date of Birth" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="calendar.open($event, 'dob')"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
<div class="col-lg-6">
<label for="formWinDate">Win Date</label>
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="{{calendar.dateFormat}}" ng-model="record.winDate" is-open="calendar.opened.win" datepicker-options="calendar.dateOptions" close-text="Close" placeholder="Win DAte" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="calendar.open($event, 'win')"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
wayne's answer is great. I would only add, that you can make the function 'open()' better:
$scope.open = function ($event, datePicker) {
$event.preventDefault();
$event.stopPropagation();
$scope.closeAll();
datePicker.opened = true;
};
And then you have to use it like that:
ng-click="open($event, dateFrom)"
Where dateFrom is your ng-model (i.e. you use $scope.dateFrom).
EDIT: $scope.closeAll(); is a function that closes all the datePickers. It can be written like that:
$scope.closeAll = function() {
$scope.dateFrom.opened = false;
$scope.dateTo.opened = false;
};
I'd prefer not to mix ng-model with UI info.For this purpose, is necessary to define an array to store the opening flags, as well as checking if the datePicker is opened or not.
Moreover, I have changes the 'open' behavior to 'toggle' instead, in order to allow closinf the datePicker with the button.
Here is my controller:
$scope.toggleOpenDatePicker = function($event,datePicker) {
$event.preventDefault();
$event.stopPropagation();
$scope[datePicker] = !$scope[datePicker];
};
Then it can be used as:
<input type="text" class="form-control" ng-model="model.date1" is-open="date1" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="toggleOpenDatePicker($event,'date1')"><i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
The $scope idea was borrowed from here:
I solved my problem by use this plunker with minor changes.
HTML
<div class="row">
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="openDatePickers[0]" 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, 0)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
<h4>Popup</h4>
<div class="row">
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="openDatePickers[1]" 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, 1)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
and in controller
$scope.openDatePickers = [];
$scope.open = function ($event, datePickerIndex) {
$event.preventDefault();
$event.stopPropagation();
if ($scope.openDatePickers[datePickerIndex] === true) {
$scope.openDatePickers.length = 0;
} else {
$scope.openDatePickers.length = 0;
$scope.openDatePickers[datePickerIndex] = true;
}
};
my changes
instead numbers (0 or 1) i use $index in angular ng-repeat.
like this:
is-open="openDatePickers[**$index**]"
ng-click="open($event, **$index**)"
<p class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="openDatePickers[$index]" 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, $index)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
i used it in a different way and it looks a bit easier to me. I was using one of the mentioned approaches, but i was to lazy to create tons of calendars since i was running i a loop without having any static identifier.
So this solution is just valid for you, if you want to create lots of calendars inside of a ng-repeat. Hope it helps!
That is the controller
$scope.datepickers = {
data: {},
isopen: {}
}
// setting the defaults once
for (var i = 0; i < $scope.array.length; i++) {
$scope.datepickers.isopen[i] = false;
$scope.datepickers.data[i] = new Date();
}
// aso..
$scope.valuationDatePickerOpen = function($event, index) {
if ($event) {
$event.preventDefault();
$event.stopPropagation();
}
$scope.datepickers.isopen[index] = true;
};
And this is the HTML snipped inside my loop
<!-- ng-repeat="entry in array track by $index" -->
<input type="text" class="form-control"
datepicker-popup="dd-MMMM-yyyy"
is-open="datepickers.isopen[$index]"
ng-click="valuationDatePickerOpen($event, $index)"
ng-model="entry.date" />

Categories