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

Commit 9d434e3

Browse files
devversionkara
authored andcommitted
fix(autofocus) properly parse attribute expression (#9636)
The autofocus directive right now works with an empty value because jqLite just toggles the class if the `force` param is `undefined`. This means if you change it several times to the same undefined value it does incorrectly update the autofocus class (which is required for the focus target) Also the autofocus directive does now determine the class immediately and does not require a second digest (previously this could cause issues with the $mdCompiler linking).
1 parent ebc8ace commit 9d434e3

File tree

2 files changed

+57
-9
lines changed

2 files changed

+57
-9
lines changed

src/core/util/autofocus.js

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,40 @@ angular.module('material.core')
9090
* </div>
9191
* </hljs>
9292
**/
93-
function MdAutofocusDirective() {
93+
function MdAutofocusDirective($parse) {
9494
return {
9595
restrict: 'A',
96-
link: postLink
96+
link: {
97+
pre: preLink
98+
}
9799
};
98-
}
99100

100-
function postLink(scope, element, attrs) {
101-
var attr = attrs.mdAutoFocus || attrs.mdAutofocus || attrs.mdSidenavFocus;
101+
function preLink(scope, element, attr) {
102+
var attrExp = attr.mdAutoFocus || attr.mdAutofocus || attr.mdSidenavFocus;
103+
104+
// Initially update the expression by manually parsing the expression as per $watch source.
105+
updateExpression($parse(attrExp)(scope));
106+
107+
// Only watch the expression if it is not empty.
108+
if (attrExp) {
109+
scope.$watch(attrExp, updateExpression);
110+
}
111+
112+
/**
113+
* Updates the autofocus class which is used to determine whether the attribute
114+
* expression evaluates to true or false.
115+
* @param {string|boolean} value Attribute Value
116+
*/
117+
function updateExpression(value) {
118+
119+
// Rather than passing undefined to the jqLite toggle class function we explicitly set the
120+
// value to true. Otherwise the class will be just toggled instead of being forced.
121+
if (angular.isUndefined(value)) {
122+
value = true;
123+
}
124+
125+
element.toggleClass('md-autofocus', !!value);
126+
}
127+
}
102128

103-
// Setup a watcher on the proper attribute to update a class we can check for in $mdUtil
104-
scope.$watch(attr, function(canAutofocus) {
105-
element.toggleClass('md-autofocus', canAutofocus);
106-
});
107129
}

src/core/util/autofocus.spec.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ describe('md-autofocus', function() {
77
}));
88

99
describe('add/removes the proper classes', function() {
10+
1011
it('supports true', function() {
1112
build('<input id="test" type="text" md-autofocus="true">');
1213

@@ -34,6 +35,31 @@ describe('md-autofocus', function() {
3435
expect(element).toHaveClass('md-autofocus');
3536
});
3637

38+
it('should properly set the class at initialization', inject(function($compile, $rootScope) {
39+
pageScope = $rootScope.$new();
40+
element = $compile('<input md-autofocus>')(pageScope);
41+
42+
expect(element).toHaveClass('md-autofocus');
43+
}));
44+
45+
it('does not accidentally toggle the class', function() {
46+
build('<input md-autofocus="autofocus">');
47+
48+
// By default, we assume an empty value for the expression is true
49+
expect(element).toHaveClass('md-autofocus');
50+
51+
// Trigger a second digest, to be able to set the scope binding to undefined later again.
52+
pageScope.$apply('autofocus = true');
53+
54+
expect(element).toHaveClass('md-autofocus');
55+
56+
// Set the scope binding to undefined again, which can accidentally toggle the class due to
57+
// the jqLite toggleClass function, which just toggles the class if the value is undefined.
58+
pageScope.$apply('autofocus = undefined');
59+
60+
expect(element).toHaveClass('md-autofocus');
61+
});
62+
3763
it('supports expressions', function() {
3864
build('<input id="test" type="text" md-autofocus="shouldAutoFocus==1">');
3965

0 commit comments

Comments
 (0)