6

I want to limit the Angular UI Datepicker to be between two dates passed in as variables. Preferably I'd like to get it working without adding a library like momentjs, because this is the only field in which I need to work with dates.

Here is a plunker of this problem:

http://plnkr.co/edit/zsjpoVZtHqJLIP2RW6vm?p=preview

here are the variables:

mycurrentdate = '2016-04-18'
mymindate = '2016-04-01'
mymaxmonth = '2016-05-01'
mymaxdate will be calculated from mymaxmonth to be
mymaxdate = '2016-05-31'

My actual max date will be the the last day of mymaxmonth

$scope.maxDate = new Date(
                    $scope.mymaxmonth + (TO THE END OF THE MONTH)
                );

One thing to note is that running it through new Date() returns a date that is the day before the given date. For example:

$scope.minDate = new Date(
                    $scope.mymindate
                );

$scope.minDate returns Wed Mar 30 2016 17:00:00 GMT-0700 (PDT) I looked up the reason for why it returns March 30 instead of April 1st and it seems like a timezone error?

I want to set a mymindate of '2016-04-01' and get mymaxdate = '2016-05-31' and disable all dates outside of this range. I've read Beginners Guide to Javascript Date and Time and tried it out here.

In the controller I have:

$scope.mymindate = '2016-04-01';
$scope.mymaxmonth = '2016-05-01'; //want mymaxdate to be '2016-05-31'

 $scope.minDate = new Date($scope.dt.getFullYear(), $scope.dt.getMonth(), 1);

 $scope.maxDate = new Date($scope.dt.getFullYear(), $scope.dt.getMonth() + 1, 0);

In the template I have:

    <p class="input-group">
      <input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="dt" is-open="popup1.opened" min-date="minDate" max-date="maxDate" datepicker-options="dateOptions" 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>
4
  • "… seems like a timezone error". Not an error, a poor design decision by the authors of ECMA-262, see Why is new Date() removing a day?. The only way to avoid the poor parsing of the Date constructor (and Date.parse, they are equivalent) is to manually parse the date. So either write a function (2 lines of code) or use a library. There are many small parsing and formatting libraries on GitHub, or go for moment.js if you have other date things to do as well. Commented Apr 19, 2016 at 0:33
  • Oh, note that if you have a Date for 31-May-2016 and add one month you'll get 01-July-2016 (since there is no 31 June, it rolls over to July). Date arithmetic isn't trivial and why most use a small (or maybe large) library for such things. Commented Apr 19, 2016 at 0:39
  • @RobG This is the only time in my application i'll be using dates so I'd prefer to stay away from adding a library dependency if possible. Commented Apr 19, 2016 at 17:53
  • In that case you should use an addMonths function that checks the initial date vs the final date. If they're different it means adding a month rolled over an extra month (e.g. initial 31, final 1), so set the date to zero so it's the last day of the previous month (so 31 May + 1 Month -> 31 June -> 1 July -> set to 0 July -> 30 June. ;-) Commented Apr 19, 2016 at 22:55

2 Answers 2

5
+50

you need to set datepicker-options with proper option for your input to disable date. In your example used datepicker-options="dateOptions" but in your controller didn't declare dateOptions.

So you need to set dateOptions for maxDate and minDate. like

$scope.dateOptions = {
    maxDate: new Date($scope.maxDate),
    minDate: new Date($scope.mymindate)
};

and set maxDate and minDate like:

$scope.mymindate = new Date('2016-04-01');
$scope.mymaxmonth = new Date('2016-05-01'); //wanted mymaxdate to be '2016-05-31'

$scope.minDate = new Date($scope.mymindate);

$scope.maxDate = new Date($scope.mymaxmonth.getFullYear(),$scope.mymaxmonth.getMonth()+1,0);

and HTML:

<p class="input-group">
    <input  type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="dt" is-open="popup1.opened" min="minDate" max="maxDate" datepicker-options="dateOptions" 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>

Can see Plunker Demo and hopefully it will help you :)

Sign up to request clarification or add additional context in comments.

Comments

4

After some annoying date manipulations, I got it. Here is the working plunker: http://plnkr.co/edit/6U4YdTIyFXjOqRJm2qTq?p=preview

In my controller I have:

var mindate = new Date($scope.mymindate);
$scope.minDate = new Date(mindate.getTime()+(1*24*60*60*1000)); //Due to poor design by the authors of ECMA-262 the date is parsed to be a day behind, so we must add a day

var maxdate = new Date($scope.mymaxmonth);
$scope.maxDate = new Date(maxdate.getFullYear(), maxdate.getMonth() + 2, 0); //Add a month to get to the end of the month.

$scope.dateOptions = {
    maxDate: $scope.maxDate,
    minDate: $scope.minDate,
};

In my template:

datepicker-options="dateOptions" 

I didn't end up needing min-date or max-date because dateoptions covers both. I'll be honest, not sure why you have to add two to the macdate.getMonth() instead of just one, but it worked out.

1 Comment

according to your question maxdate='2016-05-01' and wanted disable after 2016-05-31 so if you add maxdate.getMonth() + 2 then fulfill your requirement? your demo shown disable after 2 month

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.