Anders Lindén
Anders Lindén

Reputation: 7293

Directive to update a datepicker does not update model

I am using the timepicker from https://github.com/uxsolutions/bootstrap-datepicker in an angularjs project.

The html looks like:

<div uxdatepicker ng-model="selectedDate"
  data-provide="datepicker-inline" ng-change="on_date_changed()">
</div>

I have created a directive like:

app.directive("uxdatepicker", function ()
{
    return {
        require: "ngModel",
        scope: {
            ngModel: '='
        },
        link: function (scope, element, attrs, controller)
        {
            element.datepicker({
                language: "no",
                format: "yyyy-mm-dd",
                datesDisabled : ["2017-10-10"],
                maxViewMode: "days"
            }).on("changeDate", function (e)
            {
                scope.$apply(function ()
                {
                    controller.$setViewValue(e.date);
                });
            });
        }
    };
});

But $scope.selectedDate in my main controller will never be updated with the selected date.

Why not?

I have alerted e.date in the change date handler to make sure it holds the selected date.

Upvotes: 0

Views: 455

Answers (1)

Maxim Shoustin
Maxim Shoustin

Reputation: 77904

I wrote following directive to make it work:

app.directive('wmAiGridDatePicker', ['$timeout', '$parse', function ($timeout, $parse) {
        return {//this datePicker will show the date in the wanted format and save it (ng-model) with the default format of yy-mm-dd
            template: '<input type="text"  style="cursor: pointer;border-color: rgb(239, 239, 239);height: 22px;padding-left: 6px;margin-right: 13px;margin-top: 10px;">',
            replace: true,
            require: 'ngModel',
            scope: {},
            link: function (scope, element, attrs, controller) {

                scope.time = {
                    hours: 0,
                    minutes: 0
                };

                var getModel = function () {
                    return controller.$modelValue;
                };

                var options = {
                    format: "dd/mm/yyyy"
                    , autoclose: 'true'                            
                    , todayBtn: "linked"
                    ,todayHighlight:true
                };

                element.datepicker(options);

                element.datepicker().on('hide', function () {

                    $timeout(function () {
                        var date_ = element.datepicker('getDate');

                        if (date_) {
                            date_.setHours(scope.time.hours);
                            date_.setMinutes(scope.time.minutes);                            
                            controller.$setViewValue(moment(date_).unix());
                        }


                        scope.$apply();
                    }, 1);
                });

                element.datepicker().on('changeDate', function () {

                    $timeout(function () {
                        var date_ = element.datepicker('getDate');

                        if (date_) {
                            date_.setHours(scope.time.hours);
                            date_.setMinutes(scope.time.minutes);
                            controller.$setViewValue(moment(date_).unix());
                        }


                        scope.$apply();
                    }, 1);
                });

                scope.onModelChange = function () {                   

                    var date = controller.$modelValue;

                    if (angular.isDate(date)) {
                        scope.time.hours = date.getHours();
                        scope.time.minutes = date.getMinutes();
                    }
                };

                controller.$render = function () {
                    var unixDate = controller.$modelValue;

                    if (!unixDate) {
                        return;
                    }

                    var date = new Date(unixDate * 1000);

                    if (angular.isDate(date)) {
                        scope.time.hours = date.getHours();
                        scope.time.minutes = date.getMinutes();
                    }

                    element.datepicker('setDate', date);
                    element.datepicker('update');
                };

                scope.$watch(getModel, function (newVal) {                    
                    scope.onModelChange();                 
                }, true);

                if (controller) {
                    controller.$render();
                }
            }
        };
    }]);

and HTML:

<wm-date-picker  
    ng-blur="onChange()" 
    data-ng-model="item.due">
</wm-date-picker>

Upvotes: 1

Related Questions