jQuery ui datepicker with Angularjs

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


Solution 1:

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

Solution 2:

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();
                }
            });
        }
    };
});

Solution 3:

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

Solution 4:

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. :)

Solution 5:

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/