2

I'm using JQuery UI's Datepicker on Date From and Date To fields in an AngularJS project. I've added the directive to bind the value to the model value, and I've also added a check to OnSelect that sets the minDate and maxDate options for each field (so the Date To is never earlier than the Date From). The problem is that, on loading the page, no date has actually been selected (even though the model has a value), so it is still possible to select a To date earlier than the Date From. I added a $watch service to at least correct the error, but I still can't figure out how to set the minDate on load either within the directive or inside the controller. I've also tried $(document).ready outside of the Angular code, but that isn't working either. Here's my code prior to adding anything to set the minDate.

Within controller:

$scope.messagesForm.dateFrom = moment().subtract('days', 30).format('MM/DD/YYYY');
$scope.messagesForm.dateTo = moment().format('MM/DD/YYYY');
$scope.$watch('messagesForm.dateTo', function(newVal, oldVal) {
    if (!newVal) return;
    if (Date.parse(newVal) < Date.parse($scope.messagesForm.dateFrom)) {
        $scope.messagesForm.dateFrom = newVal;
    }
});

Directive:

.directive('datepicker', function() {
return {
    restrict: 'A',
    require : 'ngModel',
    link : function (scope, element, attrs, ngModelCtrl) {
        $(function(){
            element.datepicker({
                dateFormat: 'mm/dd/yy',
                showStatus: true,
                showWeeks: true,
                highlightWeek: true,
                maxDate: 0,
                numberOfMonths: 1,
                showAnim: "scale",
                showOptions: { origin: ["bottom", "right"] },
                onSelect: function (date) {
                    if (this.id === "MessageDateFrom") {
                       $("#MessageDateTo").datepicker("option", "minDate", date);
                    } else if (this.id === "MessageDateTo") {
                        $("#MessageDateFrom").datepicker("option", "maxDate", date);
                    }
                    ngModelCtrl.$setViewValue(date);
                    scope.$apply();
                }
            });
        });
    }
}

});

HTML:

<div class="form-group">
     <input type="text" id="MessageDateFrom" class="form-control dates" ng-model="messagesForm.dateFrom" datepicker readonly="readonly" />
</div>
<div class="form-group">
     <input type="text" id="MessageDateTo" class="form-control dates" ng-model="messagesForm.dateTo" datepicker readonly="readonly" />
</div>

Failing JQuery I've attempted:

$(document).ready(function() {
    $("MessageDateTo").datepicker("option","minDate",$("MessageDateFrom").val());
};

Any ideas?

Thanks!

3
  • Do you have any plunker/fiddle for this?
    – Vinay K
    Commented Feb 26, 2015 at 18:03
  • No, I'll try to put one together.
    – spjpdx
    Commented Feb 26, 2015 at 18:11
  • This has all the relevant code and libraries but for some reason Plunker is not processing the JS file correctly. plnkr.co/edit/cvVSoYJuAz1gk0Pst9wN
    – spjpdx
    Commented Feb 26, 2015 at 18:43

2 Answers 2

3

No need to worries about when controller loads or what just add this two property which is minDate & maxDate with there limit like minDate:"-30d",maxDate: 0,

You also can place minDate and maxDate values dynamically from directive property.

Directive

app.directive('datepicker', function() {
    return {
        restrict: 'A',
        require : 'ngModel',
        link : function (scope, element, attrs, ngModelCtrl) {
            $(function(){
                element.datepicker({
                    dateFormat: 'mm/dd/yy',
                    showStatus: true,
                    showWeeks: true,
                    highlightWeek: true,
                    minDate:"-30d", //here i did logic -30d
                    maxDate: 0, //today is max date
                    numberOfMonths: 1,
                    showAnim: "scale",
                    showOptions: { origin: ["bottom", "right"] },
                    onSelect: function (date) {
                        ngModelCtrl.$setViewValue(date);
                        scope.$apply();
                    }
                });
            });
        }
    }
});

Working Plunkr

Update

Sorry for my wrong assumption, If you really do care about whenever the data gets loaded or date variable are assigned at that time jquery ui datepicker should bind to them, then I'll prefer to use attrs.$observe which will gets call whenever your attribute expression gets evaluated. For make it working I did added one attribute name loaded="{{messagesForm.dateFrom}}" & loaded="{{messagesForm.dateTo}}" on the page so whenever the value gets assigned to dateFrom and dateTo the respective datepicker will get assign to their elements

Directive

 app.directive('datepicker', function() {
    return {
        restrict: 'A',
        require : 'ngModel',
        link : function (scope, element, attrs, ngModelCtrl) {
            //get called when `{{}}` value evaluated
            attrs.$observe('loaded',function(val){
              element.datepicker({
                  dateFormat: 'mm/dd/yy',
                  showStatus: true,
                  showWeeks: true,
                  highlightWeek: true,
                  maxDate: 0,
                  numberOfMonths: 1,
                  showAnim: "scale",
                  showOptions: { origin: ["bottom", "right"] },
                  onSelect: function (date) {
                      if (this.id === "MessageDateFrom") {
                         $("#MessageDateTo").datepicker("option", "minDate", date);
                      } else if (this.id === "MessageDateTo") {
                          $("#MessageDateFrom").datepicker("option", "maxDate", date);
                      }
                      ngModelCtrl.$setViewValue(date);
                      scope.$apply();
                  }
              });
            })

        }
    }
});

Updated Plunkr with demonstration of setting value of scope variables after 5 sec.

Hope this could help you, Thanks.

3
  • Thanks, but that's not quite what I'm looking for. I don't want the minDate on the DateFrom to be limited to 30 days back, only the DateTo, and only on initial load. After the initial load, I need the DateFrom and DateTo to update each other's min and max dates dynamically. Where can I set the individual options? Whenever I try to do it with JQuery it doesn't seem to work because of the Angular directive conflicting.
    – spjpdx
    Commented Feb 26, 2015 at 23:49
  • I actually think $timeout was the answer in conjunction with your other suggestions, so thanks for that. Check out an updated plunk: plnkr.co/edit/BmM1YgvpT2kioSg5smq4?p=preview
    – spjpdx
    Commented Mar 2, 2015 at 16:30
  • @spjpdx doing DOM manipulation from controller is antipattern in angular github.com/angular/angular.js/wiki/Anti-Patterns..please don't to that either use attr.$observe/$timeout/scope.$evalAsync Commented Mar 2, 2015 at 17:04
0

update the minDate and maxDate in $timeout.

$timeout will make sure that the directive is rendered.

Here is the updated plunker. http://plnkr.co/edit/2ucTcwKFPFpgxoJiRB3f?p=preview

4
  • please check he want to change min and max date dynamically..and what you mentioned.I already fixed it.. Commented Feb 27, 2015 at 11:04
  • @pankajparkar, I overlooked it. Thanks for that. Updated the plunker.
    – Vinay K
    Commented Feb 27, 2015 at 11:16
  • please confirm it yourself first..refer comment in my answer Commented Feb 27, 2015 at 11:23
  • He handled that logic in the onSelect.
    – Vinay K
    Commented Feb 27, 2015 at 11:26

Not the answer you're looking for? Browse other questions tagged or ask your own question.