How to use datepicker directive with AngularJS and Bootstrap

This post shows you how to fix the datepicker not binding value when using AngularJS.

By default, you always get 'undefine' when using data binding with datepicker in controller. To solve the problem, you can create a directive as shown below to update your model.

(function () {
    'use strict';

    angular
        .module('app')
        .directive('datepicker', datepicker);

    function datepicker() {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, ctrl) {
                var datepickerFormat = 'dd/mm/yyyy',
                    momentFormat = 'DD/MM/YYYY',
                    datepicker;

                datepicker = element.datepicker({
                    autoclose: true,
                    keyboardNavigation: false,
                    todayHighlight: true,
                    dateFormat: datepickerFormat
                });

                datepicker.on('changeDate', function (evt) {
                    if (evt.target.tagName == 'INPUT') {
                        ctrl.$setViewValue(moment(evt.date).format(momentFormat));
                        ctrl.$render();
                    }
                });
            }
        };
    }
})();

Using directive in angularjs allows you to extend HTML with new attributes. You should add bootstrap-datepicker.js, moment.min.js to your web page, then add the datepicker attribute to your html template as the following.

<input type="text" datepicker ng-model="FromDate" class="form-control" placeholder="From date" />

Now, you can get the value from datepicker in your controller

(function () {
    'use strict';

    angular
        .module('app')
        .controller('reportController', reportController);

    reportController.$inject = ['$scope'];

    function reportController($scope) {

        $scope.filterInvoice = function () {
            var filter = {
                FromDate: moment($scope.FromDate, "DD/MM/YYYY").format("MM/DD/YYYY"),
                ToDate: moment($scope.ToDate, "DD/MM/YYYY").format("MM/DD/YYYY")
            };
        }        
    }
})();