jQuery UI Datepicker with AngularJS

Yesterday I had to implement jQuery’s Datepicker with Angularjs, at first I thought it would be straight forward, just a directive to configure the datepicker and setup the input field, but I found there is more behind it. The calendar was working fine but the model were not being updated with the selected date. So after some research I came up with the solution bellow:

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

The directive is restricted to an attribute and the link() function is used to setup the datepicker. The interesting part in inside the onSelected method, there I am using the ngModelController to update the model using it’s $setViewValue method.

The ngModelController

“NgModelController provides API for the ng-model directive. The controller contains services for data-binding, validation, CSS update, value formatting and parsing. It specifically does not contain any logic which deals with DOM rendering or listening to DOM events. The NgModelController is meant to be extended by other directives where, the directive provides DOM manipulation and the NgModelController provides the data-binding.” – Angular Docs

In my opinion this is the best solutions because you rely only on the ngModel directive for the two-way data bind, there is no need to use $parse or reach the model directly through the scope.

You can try it here.

EDIT: As pointed by jsanti, don’t forget to include the scripts in order:

1 – Jquery
2 – Jquery-ui
3 – angularjs.

Otherwise Angular will use JQlite intead of JQuery and the directive will break.

EDIT: As pointed by Craig, wrapp ngModelCtrl.$setViewValue(date) with scope.$apply().