Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 1a2b1a8

Browse files
crisbetoThomasBurleson
authored andcommitted
fix(checkbox): avoid potential memory leaks, general cleanup
* Avoids potential memory leaks in the checkbox component by removing any event handlers from the `compile` function and avoiding references between `compile` and `link`. * Cleans out a few redundancies in the checkbox link function. Fixes #7993. Closes #9130
1 parent 11cbe3a commit 1a2b1a8

File tree

2 files changed

+28
-34
lines changed

2 files changed

+28
-34
lines changed

src/components/checkbox/checkbox.js

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ angular
3131
* @param {expression=} md-indeterminate This determines when the checkbox should be rendered as 'indeterminate'.
3232
* If a truthy expression or no value is passed in the checkbox renders in the md-indeterminate state.
3333
* If falsy expression is passed in it just looks like a normal unchecked checkbox.
34-
* The indeterminate, checked, and unchecked states are mutually exclusive. A box cannot be in any two states at the same time.
35-
* Adding the 'md-indeterminate' attribute overrides any checked/unchecked rendering logic.
34+
* The indeterminate, checked, and unchecked states are mutually exclusive. A box cannot be in any two states at the same time.
35+
* Adding the 'md-indeterminate' attribute overrides any checked/unchecked rendering logic.
3636
* When using the 'md-indeterminate' attribute use 'ng-checked' to define rendering logic instead of using 'ng-model'.
37-
* @param {expression=} ng-checked If this expression evaluates as truthy, the 'md-checked' css class is added to the checkbox and it
37+
* @param {expression=} ng-checked If this expression evaluates as truthy, the 'md-checked' css class is added to the checkbox and it
3838
* will appear checked.
3939
*
4040
* @usage
@@ -56,7 +56,6 @@ angular
5656
*/
5757
function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $mdUtil, $timeout) {
5858
inputDirective = inputDirective[0];
59-
var CHECKED_CSS = 'md-checked';
6059

6160
return {
6261
restrict: 'E',
@@ -76,32 +75,35 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $
7675
// **********************************************************
7776

7877
function compile (tElement, tAttrs) {
79-
var container = tElement.children();
80-
var mdIndeterminateStateEnabled = $mdUtil.parseAttributeBoolean(tAttrs.mdIndeterminate);
81-
8278
tAttrs.$set('tabindex', tAttrs.tabindex || '0');
8379
tAttrs.$set('type', 'checkbox');
8480
tAttrs.$set('role', tAttrs.type);
8581

86-
// Attach a click handler in compile in order to immediately stop propagation
87-
// (especially for ng-click) when the checkbox is disabled.
88-
tElement.on('click', function(event) {
89-
if (this.hasAttribute('disabled')) {
90-
event.stopImmediatePropagation();
91-
}
92-
});
93-
94-
// Redirect focus events to the root element, because IE11 is always focusing the container element instead
95-
// of the md-checkbox element. This causes issues when using ngModelOptions: `updateOnBlur`
96-
container.on('focus', function() {
97-
tElement.focus();
98-
});
82+
return {
83+
pre: function(scope, element) {
84+
// Attach a click handler during preLink, in order to immediately stop propagation
85+
// (especially for ng-click) when the checkbox is disabled.
86+
element.on('click', function(e) {
87+
if (this.hasAttribute('disabled')) {
88+
e.stopImmediatePropagation();
89+
}
90+
});
91+
},
92+
post: postLink
93+
};
9994

100-
return function postLink(scope, element, attr, ngModelCtrl) {
95+
function postLink(scope, element, attr, ngModelCtrl) {
10196
var isIndeterminate;
10297
ngModelCtrl = ngModelCtrl || $mdUtil.fakeNgModel();
10398
$mdTheming(element);
104-
if (mdIndeterminateStateEnabled) {
99+
100+
// Redirect focus events to the root element, because IE11 is always focusing the container element instead
101+
// of the md-checkbox element. This causes issues when using ngModelOptions: `updateOnBlur`
102+
element.children().on('focus', function() {
103+
element.focus();
104+
});
105+
106+
if ($mdUtil.parseAttributeBoolean(attr.mdIndeterminate)) {
105107
setIndeterminateState();
106108
scope.$watch(attr.mdIndeterminate, setIndeterminateState);
107109
}
@@ -162,11 +164,7 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $
162164
var keyCode = ev.which || ev.keyCode;
163165
if (keyCode === $mdConstant.KEY_CODE.SPACE || keyCode === $mdConstant.KEY_CODE.ENTER) {
164166
ev.preventDefault();
165-
166-
if (!element.hasClass('md-focused')) {
167-
element.addClass('md-focused');
168-
}
169-
167+
element.addClass('md-focused');
170168
listener(ev);
171169
}
172170
}
@@ -182,17 +180,13 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $
182180
// Toggle the checkbox value...
183181
var viewValue = attr.ngChecked ? attr.checked : !ngModelCtrl.$viewValue;
184182

185-
ngModelCtrl.$setViewValue( viewValue, ev && ev.type);
183+
ngModelCtrl.$setViewValue(viewValue, ev && ev.type);
186184
ngModelCtrl.$render();
187185
});
188186
}
189187

190188
function render() {
191-
if(ngModelCtrl.$viewValue && !isIndeterminate) {
192-
element.addClass(CHECKED_CSS);
193-
} else {
194-
element.removeClass(CHECKED_CSS);
195-
}
189+
element.toggleClass('md-checked', ngModelCtrl.$viewValue && !isIndeterminate);
196190
}
197191

198192
function setIndeterminateState(newValue) {

src/components/switch/switch.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function MdSwitch(mdCheckboxDirective, $mdUtil, $mdConstant, $parse, $$rAF, $mdG
6666
};
6767

6868
function mdSwitchCompile(element, attr) {
69-
var checkboxLink = checkboxDirective.compile(element, attr);
69+
var checkboxLink = checkboxDirective.compile(element, attr).post;
7070
// No transition on initial load.
7171
element.addClass('md-dragging');
7272

0 commit comments

Comments
 (0)