Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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'.

share|improve this question
5  
try $(element).datepicker() –  madhead Aug 9 '13 at 14:53
    
ok, thanks for your help, but I want to know why? would you tell me what' different about both? –  user2473037 Aug 10 '13 at 6:05
    
element may be only a jQLite wrapper, not fully functional jQuery object. –  madhead Aug 10 '13 at 11:38
    
ok, thanks a lot –  user2473037 Aug 12 '13 at 1:14
    
I had the same problem and @madhead 's solution solved it. Thanks –  Nahn Feb 10 '14 at 14:19

9 Answers 9

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)

share|improve this answer

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();
                }
            });
        }
    };
});
share|improve this answer

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

share|improve this answer
1  
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. –  Romain Paulus Mar 14 '14 at 20:50
    
Although I fixed the issue you described, I just realized that @vicont's answer is better. Much more elegant. –  Nahn Aug 1 '14 at 19:22

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();
            });
        }
    };
});
share|improve this answer
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();
                }
            });
        }
    };
});
share|improve this answer
1  
this answer works greatly, even with nested attributes, while the following one sadly doesnt. –  Stormsson Jun 5 '14 at 16:08
    
Works great, thanks –  Seth T Jan 22 at 20:03

check this hope it will help you:

http://jsbin.com/IKEXOSE/4/edit

share|improve this answer

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/

share|improve this answer

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

share|improve this answer
    
OK, Thank you !! –  user2473037 Sep 17 '13 at 0:20
    
What should I do to have a datepicker icon(clickable) next to the text box? –  kumareloaded Dec 19 '14 at 11:24

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.

share|improve this answer
1  
no,my datepicker is from jquery ui –  user2473037 Aug 9 '13 at 10:07
    
Angular ui bootrstrap acts as a bridge between jquery ui's datepicker and Angular, that may be what you're looking for –  Raibaz Aug 9 '13 at 10:14
    
it's not work? what's the problem? –  user2473037 Aug 9 '13 at 10:18

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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