Angular - ui-bootstrap - datepicker - Is there a way of detecting when the month has changed?

后端 未结 4 889
[愿得一人]
[愿得一人] 2020-12-20 21:03

I\'d like to set the date to the 1st of the currently selected month when it\'s changed.

is there a way without monitoring click event on the month\'s buttons?

4条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-20 21:39

    It's unfortunate that the datepicker directive doesn't have a binding to track the month/year change. Here is what I came up with as a work around.

    In the html...

    
    

    In the controller...

    $scope.changeMonth = function(month, year) {
        console.log(month, year);
        // set your date here if you need to
        // in my case, i needed to request some results via ajax
    };
    

    The decorator

    app.config(function($provide) {
        $provide.decorator('datepickerDirective', function($delegate) {
            var directive = $delegate[0],
                link = directive.link;
    
            angular.extend(directive.scope, { 'monthChanged': '&' });
    
            directive.compile = function() {
                return function(scope, element, attrs, ctrl) {
                    link.apply(this, arguments);
    
                    scope.$watch(function() {
                        return ctrl[0].activeDate.getTime();
                    }, function(newVal, oldVal) {
                        if (scope.datepickerMode == 'day') {
                            oldVal = moment(oldVal).format('MM-YYYY');
                            newVal = moment(newVal).format('MM-YYYY');
    
                            if (oldVal !== newVal) {
                                var arr = newVal.split('-');
                                scope.monthChanged({ '$month': arr[0], '$year': arr[1] });
                            }
                        }
                    });
                };
            };
            return $delegate;
        });
    });
    

    Another decorator

    Here is another decorator that also works but probably a bit more resource intensive. All I do here is override the isActive() method already used in the directive so my method is called instead. I'm only posting this as an example of the possible ways to work around some of the restrictions in 3rd party directives. I don't necessarily recommend this solution.

    app.config(function($provide) {
        $provide.decorator('datepickerDirective', function($delegate) {
            var directive = $delegate[0],
                link = directive.link;
    
            angular.extend(directive.scope, { 'monthChanged': '&' });
    
            directive.compile = function() {
                return function(scope, element, attrs, ctrl) {
                    link.apply(this, arguments);
    
                    var activeMonth, activeYear, activeFn = scope.isActive;
    
                    scope.isActive = function(dateObj) {
                        if (scope.datepickerMode == 'day' && !dateObj.secondary) {
                            var oldMonth = activeMonth, oldYear = activeYear,
                                newMonth = dateObj.date.getMonth() + 1;
                                newYear = dateObj.date.getFullYear();
    
                            if (oldMonth !== newMonth || oldYear !== newYear) {
                                activeMonth = newMonth;
                                activeYear = newYear;
                                scope.monthChanged({ '$month': newMonth, '$year': newYear });
                            }
                        }
                        activeFn(dateObj);
                    };
                };
            };
            return $delegate;
        });
    });
    

提交回复
热议问题