@@ -26,7 +26,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
26
26
function ( $scope , $attrs , $parse , $interpolate , $log , dateFilter , datepickerConfig , $datepickerSuppressError , dateParser ) {
27
27
var self = this ,
28
28
ngModelCtrl = { $setViewValue : angular . noop } , // nullModelCtrl;
29
- ngModelOptions = { } ;
29
+ ngModelOptions = { } ,
30
+ watchListeners = [ ] ;
30
31
31
32
// Modes chain
32
33
this . modes = [ 'day' , 'month' , 'year' ] ;
@@ -44,24 +45,24 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
44
45
// Watchable date attributes
45
46
angular . forEach ( [ 'minDate' , 'maxDate' ] , function ( key ) {
46
47
if ( $attrs [ key ] ) {
47
- $scope . $parent . $watch ( $attrs [ key ] , function ( value ) {
48
+ watchListeners . push ( $scope . $parent . $watch ( $attrs [ key ] , function ( value ) {
48
49
self [ key ] = value ? angular . isDate ( value ) ? dateParser . fromTimezone ( new Date ( value ) , ngModelOptions . timezone ) : new Date ( dateFilter ( value , 'medium' ) ) : null ;
49
50
self . refreshView ( ) ;
50
- } ) ;
51
+ } ) ) ;
51
52
} else {
52
53
self [ key ] = datepickerConfig [ key ] ? dateParser . fromTimezone ( new Date ( datepickerConfig [ key ] ) , ngModelOptions . timezone ) : null ;
53
54
}
54
55
} ) ;
55
56
56
57
angular . forEach ( [ 'minMode' , 'maxMode' ] , function ( key ) {
57
58
if ( $attrs [ key ] ) {
58
- $scope . $parent . $watch ( $attrs [ key ] , function ( value ) {
59
+ watchListeners . push ( $scope . $parent . $watch ( $attrs [ key ] , function ( value ) {
59
60
self [ key ] = $scope [ key ] = angular . isDefined ( value ) ? value : $attrs [ key ] ;
60
61
if ( key === 'minMode' && self . modes . indexOf ( $scope . datepickerMode ) < self . modes . indexOf ( self [ key ] ) ||
61
62
key === 'maxMode' && self . modes . indexOf ( $scope . datepickerMode ) > self . modes . indexOf ( self [ key ] ) ) {
62
63
$scope . datepickerMode = self [ key ] ;
63
64
}
64
- } ) ;
65
+ } ) ) ;
65
66
} else {
66
67
self [ key ] = $scope [ key ] = datepickerConfig [ key ] || null ;
67
68
}
@@ -72,22 +73,22 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
72
73
73
74
if ( angular . isDefined ( $attrs . initDate ) ) {
74
75
this . activeDate = dateParser . fromTimezone ( $scope . $parent . $eval ( $attrs . initDate ) , ngModelOptions . timezone ) || new Date ( ) ;
75
- $scope . $parent . $watch ( $attrs . initDate , function ( initDate ) {
76
+ watchListeners . push ( $scope . $parent . $watch ( $attrs . initDate , function ( initDate ) {
76
77
if ( initDate && ( ngModelCtrl . $isEmpty ( ngModelCtrl . $modelValue ) || ngModelCtrl . $invalid ) ) {
77
78
self . activeDate = dateParser . fromTimezone ( initDate , ngModelOptions . timezone ) ;
78
79
self . refreshView ( ) ;
79
80
}
80
- } ) ;
81
+ } ) ) ;
81
82
} else {
82
83
this . activeDate = new Date ( ) ;
83
84
}
84
85
85
86
$scope . disabled = angular . isDefined ( $attrs . disabled ) || false ;
86
87
if ( angular . isDefined ( $attrs . ngDisabled ) ) {
87
- $scope . $parent . $watch ( $attrs . ngDisabled , function ( disabled ) {
88
+ watchListeners . push ( $scope . $parent . $watch ( $attrs . ngDisabled , function ( disabled ) {
88
89
$scope . disabled = disabled ;
89
90
self . refreshView ( ) ;
90
- } ) ;
91
+ } ) ) ;
91
92
}
92
93
93
94
$scope . isActive = function ( dateObject ) {
@@ -248,6 +249,13 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
248
249
self . refreshView ( ) ;
249
250
}
250
251
} ;
252
+
253
+ $scope . $on ( "$destroy" , function ( ) {
254
+ //Clear all watch listeners on destroy
255
+ while ( watchListeners . length ) {
256
+ watchListeners . shift ( ) ( ) ;
257
+ }
258
+ } ) ;
251
259
} ] )
252
260
253
261
. controller ( 'UibDaypickerController' , [ '$scope' , '$element' , 'dateFilter' , function ( scope , $element , dateFilter ) {
@@ -573,12 +581,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
573
581
574
582
. controller ( 'UibDatepickerPopupController' , [ '$scope' , '$element' , '$attrs' , '$compile' , '$parse' , '$document' , '$rootScope' , '$uibPosition' , 'dateFilter' , 'uibDateParser' , 'uibDatepickerPopupConfig' , '$timeout' , 'uibDatepickerConfig' ,
575
583
function ( scope , element , attrs , $compile , $parse , $document , $rootScope , $position , dateFilter , dateParser , datepickerPopupConfig , $timeout , datepickerConfig ) {
576
- var self = this ;
577
584
var cache = { } ,
578
585
isHtml5DateInput = false ;
579
586
var dateFormat , closeOnDateSelection , appendToBody , onOpenFocus ,
580
587
datepickerPopupTemplateUrl , datepickerTemplateUrl , popupEl , datepickerEl ,
581
- ngModel , ngModelOptions , $popup , altInputFormats ;
588
+ ngModel , ngModelOptions , $popup , altInputFormats , watchListeners = [ ] ;
582
589
583
590
scope . watchData = { } ;
584
591
@@ -683,7 +690,7 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi
683
690
if ( attrs [ key ] ) {
684
691
var getAttribute = $parse ( attrs [ key ] ) ;
685
692
686
- scope . $parent . $watch ( getAttribute , function ( value ) {
693
+ watchListeners . push ( scope . $parent . $watch ( getAttribute , function ( value ) {
687
694
if ( key === 'minDate' || key === 'maxDate' ) {
688
695
if ( value === null ) {
689
696
cache [ key ] = null ;
@@ -697,7 +704,7 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi
697
704
} else {
698
705
scope . watchData [ key ] = dateParser . fromTimezone ( new Date ( value ) , ngModelOptions . timezone ) ;
699
706
}
700
- } ) ;
707
+ } ) ) ;
701
708
702
709
datepickerEl . attr ( cameltoDash ( key ) , 'watchData.' + key ) ;
703
710
}
@@ -729,7 +736,7 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi
729
736
}
730
737
scope . date = dateParser . fromTimezone ( value , ngModelOptions . timezone ) ;
731
738
dateFormat = dateFormat . replace ( / M ! / , 'MM' )
732
- . replace ( / d ! / , 'dd' ) ;
739
+ . replace ( / d ! / , 'dd' ) ;
733
740
734
741
return dateFilter ( scope . date , dateFormat ) ;
735
742
} ) ;
@@ -769,6 +776,11 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi
769
776
$popup . remove ( ) ;
770
777
element . unbind ( 'keydown' , inputKeydownBind ) ;
771
778
$document . unbind ( 'click' , documentClickBind ) ;
779
+
780
+ //Clear all watch listeners on destroy
781
+ while ( watchListeners . length ) {
782
+ watchListeners . shift ( ) ( ) ;
783
+ }
772
784
} ) ;
773
785
} ;
774
786
@@ -782,7 +794,7 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi
782
794
}
783
795
784
796
return scope . watchData . minDate && scope . compare ( date , cache . minDate ) < 0 ||
785
- scope . watchData . maxDate && scope . compare ( date , cache . maxDate ) > 0 ;
797
+ scope . watchData . maxDate && scope . compare ( date , cache . maxDate ) > 0 ;
786
798
} ;
787
799
788
800
scope . compare = function ( date1 , date2 ) {
@@ -832,9 +844,9 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi
832
844
833
845
scope . disabled = angular . isDefined ( attrs . disabled ) || false ;
834
846
if ( attrs . ngDisabled ) {
835
- scope . $parent . $watch ( $parse ( attrs . ngDisabled ) , function ( disabled ) {
847
+ watchListeners . push ( scope . $parent . $watch ( $parse ( attrs . ngDisabled ) , function ( disabled ) {
836
848
scope . disabled = disabled ;
837
- } ) ;
849
+ } ) ) ;
838
850
}
839
851
840
852
scope . $watch ( 'isOpen' , function ( value ) {
0 commit comments