Imagine you need to include in a project AngularJs, the Bootstrap Datepicker: first of all you need to create your boilerplate with relevant restrictions and configurations.

angular.module("corley.bootstrap-datepicker", [])
    .directive("crBootstrapDatepicker", function(){
        return {
            restrict: "EAC"
            }
        };
    });

Then on top of the input element, you need to initialize the Datepicker: for this purpose you must be inside the link function and call the function; but now there is the problem that the current scope has lost the value state.

angular.module("corley.bootstrap-datepicker", [])
    .directive("crBootstrapDatepicker", function(){
        return {
            restrict: "EAC",
            link: function(scope, elem, attr){
                $(elem).datepicker({
                    format: "mm/dd/yyyy",
                })
            }
        };
    });

To solve this first problem, you can link to the 'change Date' event, provided by the library, then you can force the scope updating: for this purpose your directive must contain the dependency "ngModel", to know the element to which assign the new date.

angular.module("corley.bootstrap-datepicker", [])
    .directive("crBootstrapDatepicker", function(){
        return {
            restrict: "EAC",
            require: "ngModel",
            scope: {
                "ngModel": "="
            },
            link: function(scope, elem, attr){
                $(elem).datepicker({
                    format: "mm/dd/yyyy",
                }).on("changeDate", function(e){
                    return scope.$apply(function(){
                        return scope.ngModel = e.format();
                    });
                });
            }
        };
    });

Image you use the directive in the following way.

angular.module("corley.bootstrap-datepicker", [])
    .directive("crBootstrapDatepicker", function(){
        return {
            restrict: "EAC",
            require: "ngModel",
            scope: {
                "ngModel": "="
            },
            link: function(scope, elem, attr){
                $(elem).datepicker({
                    format: "mm/dd/yyyy",
                }).on("changeDate", function(e){
                    return scope.$apply(function(){
                        return scope.ngModel = e.format();
                    });
                });

                return scope.$watch("ngModel", function(newValue){
                    $(elem).datepicker("update", newValue);
                });
            }
        };
    });

Now let's provide a real implementation of such directive

view.html

<input cr-bootstrap-datepicker ng-model="myDate">

controller.js

.controller( "HomeCtrl", function HomeController( $scope, $stateParams ) { 
    $scope.myDate = "01/01/2014";
});

You can see Angular is before compiling the directive and then is assigning the real my Data value of your Scope to the Input field: this can cause inconsistencies in the Datepicker.

To solve such problem, you need to perform an update of Datepicker, once the ngModel value is really being replaced.

angular.module("corley.bootstrap-datepicker", [])
    .directive("crBootstrapDatepicker", function(){
        return {
            restrict: "EAC",
            require: "ngModel",
            scope: {
                "ngModel": "="
            },
            link: function(scope, elem, attr){
                $(elem).datepicker({
                    format: "mm/dd/yyyy",
                }).on("changeDate", function(e){
                    return scope.$apply(function(){
                        return scope.ngModel = e.format();
                    });
                });

                return scope.$watch("ngModel", function(newValue){
                    $(elem).datepicker("update", newValue);
                });
            }
        };
    });

Comments

comments powered by Disqus

cloudparty

Follow Us