51

I want to use jQuery UI datepicker with AngularJS.

I have a sample , but my code is not working.

Sample:

http://www.abequar.net/jquery-ui-datepicker-with-angularjs/

My Code:

<input id="sDate" name="programStartDate" type="text" datepicker required/>



angular.module('elnApp')
 .directive('datepicker', function () {
  return {
    restrict: 'A',
    require : 'ngModel',
    link : function (scope, element, attrs, ngModelCtrl) {
        $(function(){
            element.datepicker({
                dateFormat:'yy-mm-dd',
                onSelect:function (date) {
                    ngModelCtrl.$setViewValue(date);
                    scope.$apply();

                }
            });
        });
    }
} });

It shows an error TypeError: Object [object Object] has no method 'datepicker'.

6
  • 8
    try $(element).datepicker() Commented Aug 9, 2013 at 14:53
  • ok, thanks for your help, but I want to know why? would you tell me what' different about both? Commented Aug 10, 2013 at 6:05
  • 2
    element may be only a jQLite wrapper, not fully functional jQuery object. Commented Aug 10, 2013 at 11:38
  • Make sure you're including jQuery before Angular. It will pick that up and use the actual jQuery library rather than jQLite. See the documentation on angular.element. Commented Feb 10, 2014 at 15:55
  • If you are using dynamic id's, see this post: stackoverflow.com/questions/19733723/… Commented Jun 4, 2015 at 19:29

14 Answers 14

45

I have almost exactly the same code as you and mine works.

Do you have jQueryUI.js included in the page?

There's a fiddle here

<input type="text" ng-model="date" jqdatepicker />
<br/>
{{ date }}


var datePicker = angular.module('app', []);

datePicker.directive('jqdatepicker', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
         link: function (scope, element, attrs, ngModelCtrl) {
            element.datepicker({
                dateFormat: 'DD, d  MM, yy',
                onSelect: function (date) {
                    scope.date = date;
                    scope.$apply();
                }
            });
        }
    };
});

You'll also need the ng-app="app" somewhere in your HTML

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

6 Comments

What should I do to have a datepicker icon(clickable) next to the text box?
how to set value in ng-model if I am using multiple datepickers in a single page where each control is connected to different ng-model?
how to use css (color, ...) on the date field ?
I found , ex : element.prop("readonly", true); element.css("background-color", "transparent")
The problem with this code is your onSelect is doing "scope.date = date;" So regardless of which $scope variable you declare, whenever you select a date, it'll update the date value in "$scope.date" instead.
|
35
angular.module('elnApp')
.directive('jqdatepicker', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, ctrl) {
            $(element).datepicker({
                dateFormat: 'dd.mm.yy',
                onSelect: function(date) {
                    ctrl.$setViewValue(date);
                    ctrl.$render();
                    scope.$apply();
                }
            });
        }
    };
});

4 Comments

this answer works greatly, even with nested attributes, while the following one sadly doesnt.
THIS should be the correct answer, because here you also set the view values! thanks
How can we deal with multiple input ?
If the input field already contains a date, how to format it?
11

As a best practice, especially if you have multiple date pickers, you should not hardcode the element's scope variable name.

Instead, you should get the clicked input's ng-model and update its corresponding scope variable inside the onSelect method.

app.directive('jqdatepicker', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, ngModelCtrl) {
            $(element).datepicker({
                dateFormat: 'yy-mm-dd',

                onSelect: function(date) {
                    var ngModelName = this.attributes['ng-model'].value;

                    // if value for the specified ngModel is a property of 
                    // another object on the scope
                    if (ngModelName.indexOf(".") != -1) {
                        var objAttributes = ngModelName.split(".");
                        var lastAttribute = objAttributes.pop();
                        var partialObjString = objAttributes.join(".");
                        var partialObj = eval("scope." + partialObjString);

                        partialObj[lastAttribute] = date;
                    }
                    // if value for the specified ngModel is directly on the scope
                    else {
                        scope[ngModelName] = date;
                    }
                    scope.$apply();
                }

            });
        }
    };
});

EDIT

To address the issue that @Romain raised up (Nested Elements), I have modified my answer

2 Comments

It doesn't work if ng-model is a nested attribute. For example ng-model="delivery.date" will update the "delivery.date" property of the scope, instead of the "date" property of $scope.delivery.
Although I fixed the issue you described, I just realized that @vicont's answer is better. Much more elegant.
5

I finally was able to run datepicker directive in angular js , here are pointers

include following JS in order

  1. jquery.js
  2. jquery-ui.js
  3. angular-min.js

I added the following

<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script> 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"> </script>      

in html code

<body ng-app="myApp" ng-controller="myController">
// some other html code 
<input type="text" ng-model="date" mydatepicker />
<br/>
 {{ date }}
 //some other html code
 </body>

in the js , make sure you code for the directive first and after that add the code for controller , else it will cause issues.

date picker directive :

var app = angular.module('myApp',[]);
app.directive('mydatepicker', function () {
return {
    restrict: 'A',
    require: 'ngModel',
     link: function (scope, element, attrs, ngModelCtrl) {
        element.datepicker({
            dateFormat: 'DD, d  MM, yy',
            onSelect: function (date) {
                scope.date = date;
                scope.$apply();
            }
        });
    }
  };
});

directive code referred from above answers.

After this directive , write the controller

app.controller('myController',function($scope){
//controller code
};

TRY THIS INSTEAD in angular js

  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>  

along with jquery.js and jquery-ui.js

we can implement angular js datepicker as

<input type="date" ng-model="date" name="DOB">

This gives the built in datepicker and date is set in ng-model and can be used for further processing and validation.

Found this after lot of successful headbanging with previous approach. :)

1 Comment

Regarding <input type="date" ng-model="date" name="DOB">, how does it work. Do you have a working sample to show?
4

I modified the code and wrapped view update inside $apply().

link: function (scope, elem, attrs, ngModelCtrl){   
var updateModel = function(dateText){
    // call $apply to update the model
    scope.$apply(function(){
        ngModelCtrl.$setViewValue(dateText);
    });
};
var options = {
    dateFormat: "dd/mm/yy",
     // handle jquery date change
    onSelect: function(dateText){
        updateModel(dateText);
    }
};
 // jqueryfy the element
elem.datepicker(options);

}

working fiddle - http://jsfiddle.net/hsfid/SrDV2/1/embedded/result/

1 Comment

hi @hS4 i m try this wave but getting error like this ' option onSelect is not recognized!'
4

onSelect doesn't work well in ng-repeat, so I made another version using event bind

html

<tr ng-repeat="product in products">
<td>
    <input type="text" ng-model="product.startDate" class="form-control date-picker" data-date-format="yyyy-mm-dd" datepicker/>
</td>
</tr>

script

angular.module('app', []).directive('datepicker', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModelCtrl) {
            element.datepicker();
            element.bind('blur keyup change', function(){
                var model = attrs.ngModel;
                if (model.indexOf(".") > -1) scope[model.replace(/\.[^.]*/, "")][model.replace(/[^.]*\./, "")] = element.val();
                else scope[model] = element.val();
            });
        }
    };
});

Comments

4

Unfortunately, vicont's answer did not work for me, so I searched for another solution which is as elegant and works for nested attributes in the ng-model as well. It uses $parse and accesses the ng-model through the attrs in the linking function instead of requiring it:

myApp.directive('myDatepicker', function ($parse) {
    return function (scope, element, attrs, controller) {
      var ngModel = $parse(attrs.ngModel);
      $(function(){
        element.datepicker({
            ...
            onSelect:function (dateText, inst) {
                scope.$apply(function(scope){
                    // Change binded variable
                    ngModel.assign(scope, dateText);
                });
            }
        });
     });
    } 
});

Source: ANGULAR.JS BINDING TO JQUERY UI (DATEPICKER EXAMPLE)

Comments

2

You main Index.html file for Angular can use the body tag as the ng-view. Then all you need to do is include a script tag at the bottom of whatever page is being pulled into Index.html by Angular like so:

<script type="text/javascript">
$( function() {
    $( "#mydatepickerid" ).datepicker({changeMonth: true, changeYear: true, 
        yearRange: '1930:'+new Date().getFullYear(), dateFormat: "yy-mm-dd"});
});
</script>

Why overcomplicate things??

Comments

1

Here is my code-

var datePicker = angular.module('appointmentApp', []);

datePicker.directive('datepicker', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
         link: function (scope, element, attrs, ngModelCtrl) {
            $(element).datepicker({
                dateFormat: 'dd-mm-yy',
                onSelect: function (date) {
                    scope.appoitmentScheduleDate = date;
                    scope.$apply();
                }
            });
        }
    };
});

Comments

1
myModule.directive('jqdatepicker', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
         link: function (scope, element, attrs, ngModelCtrl) {
            element.datepicker({
                dateFormat: 'dd/mm/yy',
                onSelect: function (date) {   
                    var ar=date.split("/");
                    date=new Date(ar[2]+"-"+ar[1]+"-"+ar[0]);
                    ngModelCtrl.$setViewValue(date.getTime());
                //    scope.course.launchDate = date;
                    scope.$apply();
                }
            });

        }
    };
});

HTML Code :

<input type="text" jqdatepicker  ng-model="course.launchDate" required readonly />

1 Comment

In StackOverflow we prefer to not have just some code as an answer but have it alongside an explanation.how-to-answer. Moreover you should indent it properly.
1
var selectDate = element.datepicker({
    dateFormat:'dd/mm/yy',
    onSelect:function (date) {
        ngModelCtrl.$setViewValue(date);
        scope.$apply();
    }
}).on('changeDate', function(ev) {
    selectDate.hide();
    ngModelCtrl.$setViewValue(element.val());
    scope.$apply();
});                            

1 Comment

although the code may be sound, a little text would help others.
0

I had the same problem and it was solved by putting the references and includes in that order:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>
<link href="http://code.jquery.com/ui/1.10.3/themes/redmond/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>

var datePicker = angular.module('app', []);

datePicker.directive('jqdatepicker', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
         link: function (scope, element, attrs, ngModelCtrl) {
            element.datepicker({
                dateFormat: 'dd/mm/yy',
                onSelect: function (date) {
                    scope.date = date;
                    scope.$apply();
                }
            });
        }
    };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>
<link href="http://code.jquery.com/ui/1.10.3/themes/redmond/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>

<body ng-app="app">
<input type="text" ng-model="date" jqdatepicker />
<br/>
{{ date }}
</body>

Comments

0

i struggled alot and found a solution that is working as of 22 nov 2021!

things you have to use js/css

  1. <script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
    
  2. <script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
    
  3. <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
    
  4. <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
    

your html code in your view

<p>Date <input type="text" name="dateRange" id="dateRange" value="01/01/2018 - 01/15/2018" /></p>

jquery function handle should be inside the body of a controller for example:

app.controller('homeController', ['$location','$scope','$rootScope','$http','$cookies','$interval', function($location,$scope,$rootScope,$http,$cookies,$interval){

// your $scope.fun=async function(){} etc all comes here

//then

//jquery function call
$('#dateRange').daterangepicker({
        startDate: moment().subtract(365,'days'),
        endDate:moment(),
        opens: 'left'
    }, function(start, end, label) {
        console.log("A new date selection was made: " + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD'));
        $scope.fromDateData=start.format('YYYY-MM-DD');
        $scope.toDateData=end.format('YYYY-MM-DD');
    });
}]);

Comments

-3

I think you are missing the Angular ui bootstrap dependency in your module declaration, like this:

angular.module('elnApp', ['ui.bootstrap'])

See the doc for Angular-ui-bootstrap.

1 Comment

Angular ui bootrstrap acts as a bridge between jquery ui's datepicker and Angular, that may be what you're looking for

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.