Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
fix(timepicker): garbage collect parent watchers
Browse files Browse the repository at this point in the history
- Garbage collect parent $$watchers on $destroy

Closes #5277
  • Loading branch information
wesleycho committed Jan 16, 2016
1 parent 32b88f1 commit 3f809af
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 18 deletions.
17 changes: 17 additions & 0 deletions src/timepicker/test/timepicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2191,4 +2191,21 @@ describe('timepicker directive', function() {
expect(getModelState()).toEqual([14, 40, 25]);
});
});

describe('gc', function() {
var $scope;
beforeEach(inject(function() {
$scope = $rootScope.$new();
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($scope);
$rootScope.$digest();
}));

it('should clean up watchers', function() {
expect($scope.$$watchers.length > 1).toBe(true);

element.isolateScope().$destroy();

expect($scope.$$watchers.length).toBe(1);
});
});
});
43 changes: 25 additions & 18 deletions src/timepicker/timepicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ angular.module('ui.bootstrap.timepicker', [])

.controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) {
var selected = new Date(),
ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS;
watchers = [],
ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS;

$scope.tabindex = angular.isDefined($attrs.tabindex) ? $attrs.tabindex : 0;
$element.removeAttr('tabindex');
Expand Down Expand Up @@ -51,35 +52,35 @@ angular.module('ui.bootstrap.timepicker', [])

var hourStep = timepickerConfig.hourStep;
if ($attrs.hourStep) {
$scope.$parent.$watch($parse($attrs.hourStep), function(value) {
watchers.push($scope.$parent.$watch($parse($attrs.hourStep), function(value) {
hourStep = +value;
});
}));
}

var minuteStep = timepickerConfig.minuteStep;
if ($attrs.minuteStep) {
$scope.$parent.$watch($parse($attrs.minuteStep), function(value) {
watchers.push($scope.$parent.$watch($parse($attrs.minuteStep), function(value) {
minuteStep = +value;
});
}));
}

var min;
$scope.$parent.$watch($parse($attrs.min), function(value) {
watchers.push($scope.$parent.$watch($parse($attrs.min), function(value) {
var dt = new Date(value);
min = isNaN(dt) ? undefined : dt;
});
}));

var max;
$scope.$parent.$watch($parse($attrs.max), function(value) {
watchers.push($scope.$parent.$watch($parse($attrs.max), function(value) {
var dt = new Date(value);
max = isNaN(dt) ? undefined : dt;
});
}));

var disabled = false;
if ($attrs.ngDisabled) {
$scope.$parent.$watch($parse($attrs.ngDisabled), function(value) {
watchers.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(value) {
disabled = value;
});
}));
}

$scope.noIncrementHours = function() {
Expand Down Expand Up @@ -128,22 +129,22 @@ angular.module('ui.bootstrap.timepicker', [])

var secondStep = timepickerConfig.secondStep;
if ($attrs.secondStep) {
$scope.$parent.$watch($parse($attrs.secondStep), function(value) {
watchers.push($scope.$parent.$watch($parse($attrs.secondStep), function(value) {
secondStep = +value;
});
}));
}

$scope.showSeconds = timepickerConfig.showSeconds;
if ($attrs.showSeconds) {
$scope.$parent.$watch($parse($attrs.showSeconds), function(value) {
watchers.push($scope.$parent.$watch($parse($attrs.showSeconds), function(value) {
$scope.showSeconds = !!value;
});
}));
}

// 12H / 24H mode
$scope.showMeridian = timepickerConfig.showMeridian;
if ($attrs.showMeridian) {
$scope.$parent.$watch($parse($attrs.showMeridian), function(value) {
watchers.push($scope.$parent.$watch($parse($attrs.showMeridian), function(value) {
$scope.showMeridian = !!value;

if (ngModelCtrl.$error.time) {
Expand All @@ -156,7 +157,7 @@ angular.module('ui.bootstrap.timepicker', [])
} else {
updateTemplate();
}
});
}));
}

// Get $scope.hours in 24H mode if valid
Expand Down Expand Up @@ -518,6 +519,12 @@ angular.module('ui.bootstrap.timepicker', [])
$scope.blur = function() {
ngModelCtrl.$setTouched();
};

$scope.$on('$destroy', function() {
while (watchers.length) {
watchers.shift()();
}
});
}])

.directive('uibTimepicker', ['uibTimepickerConfig', function(uibTimepickerConfig) {
Expand Down

0 comments on commit 3f809af

Please sign in to comment.