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

Commit 7d8bc2d

Browse files
topherfangioThomasBurleson
authored andcommitted
fix(list): Copy md-icon.md-secondary attributes to button.
When an secondary md-icon was used in combination with a checkbox, the md-icon was only copying the `ng-click` attribute instead of all attributes including things like `ng-disabled`. Fix by ensuring we copy all relevant attributes to the wrapper. Fixes #3356. Closes #5716.
1 parent 58ab379 commit 7d8bc2d

File tree

2 files changed

+60
-42
lines changed

2 files changed

+60
-42
lines changed

src/components/list/list.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,7 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
136136
tEl.addClass('md-proxy-focus');
137137
} else {
138138
container = angular.element('<md-button class="md-no-style"><div class="md-list-item-inner"></div></md-button>');
139-
var copiedAttrs = ['ng-click', 'aria-label', 'ng-disabled',
140-
'ui-sref', 'href', 'ng-href', 'ng-attr-ui-sref'];
141-
angular.forEach(copiedAttrs, function(attr) {
142-
if (tEl[0].hasAttribute(attr)) {
143-
container[0].setAttribute(attr, tEl[0].getAttribute(attr));
144-
tEl[0].removeAttribute(attr);
145-
}
146-
});
139+
copyAttributes(tEl[0], container[0]);
147140
container.children().eq(0).append(tEl.contents());
148141
}
149142

@@ -153,8 +146,7 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
153146
if (secondaryItem && !isButton(secondaryItem) && secondaryItem.hasAttribute('ng-click')) {
154147
$mdAria.expect(secondaryItem, 'aria-label');
155148
var buttonWrapper = angular.element('<md-button class="md-secondary-container md-icon-button">');
156-
buttonWrapper.attr('ng-click', secondaryItem.getAttribute('ng-click'));
157-
secondaryItem.removeAttribute('ng-click');
149+
copyAttributes(secondaryItem, buttonWrapper[0]);
158150
secondaryItem.setAttribute('tabindex', '-1');
159151
secondaryItem.classList.remove('md-secondary');
160152
buttonWrapper.append(secondaryItem);
@@ -172,6 +164,17 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
172164
}
173165
}
174166

167+
function copyAttributes(item, wrapper) {
168+
var copiedAttrs = ['ng-click', 'aria-label', 'ng-disabled',
169+
'ui-sref', 'href', 'ng-href', 'ng-attr-ui-sref'];
170+
angular.forEach(copiedAttrs, function(attr) {
171+
if (item.hasAttribute(attr)) {
172+
wrapper.setAttribute(attr, item.getAttribute(attr));
173+
item.removeAttribute(attr);
174+
}
175+
});
176+
}
177+
175178
function isProxiedElement(el) {
176179
return proxiedTypes.indexOf(el.nodeName.toLowerCase()) != -1;
177180
}

src/components/list/list.spec.js

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ describe('mdListItem directive', function() {
33
var $compile, $rootScope;
44

55
beforeEach(module('material.components.list', 'material.components.checkbox', 'material.components.switch'));
6-
beforeEach(inject(function(_$compile_, _$rootScope_){
6+
beforeEach(inject(function(_$compile_, _$rootScope_) {
77
$compile = _$compile_;
88
$rootScope = _$rootScope_;
99
}));
@@ -26,16 +26,16 @@ describe('mdListItem directive', function() {
2626
return el;
2727
}
2828

29-
it('supports empty list items',function() {
29+
it('supports empty list items', function() {
3030
var list = setup('\
3131
<md-list>\
3232
<md-list-item></md-list-item>\
3333
</md-list>'
34-
);
34+
);
3535

3636
var cntr = list[0].querySelector('div');
3737

38-
if (cntr && cntr.click ) {
38+
if (cntr && cntr.click) {
3939
cntr.click();
4040
expect($rootScope.modelVal).toBe(false);
4141
}
@@ -46,7 +46,7 @@ describe('mdListItem directive', function() {
4646
var listItem = setup('<md-list-item><md-checkbox ng-model="modelVal"></md-checkbox></md-list-item>');
4747
var cntr = listItem[0].querySelector('div');
4848

49-
if (cntr && cntr.click ) {
49+
if (cntr && cntr.click) {
5050
cntr.click();
5151
expect($rootScope.modelVal).toBe(true);
5252
}
@@ -57,48 +57,48 @@ describe('mdListItem directive', function() {
5757
var listItem = setup('<md-list-item><md-switch ng-model="modelVal"></md-switch></md-list-item>');
5858
var cntr = listItem[0].querySelector('div');
5959

60-
if (cntr && cntr.click ) {
60+
if (cntr && cntr.click) {
6161
cntr.click();
6262
expect($rootScope.modelVal).toBe(true);
6363
}
6464

6565
});
6666

6767
it('should convert spacebar keypress events as clicks', inject(function($mdConstant) {
68-
var listItem = setup('<md-list-item><md-checkbox ng-model="modelVal"></md-checkbox></md-list-item>');
69-
var checkbox = angular.element(listItem[0].querySelector('md-checkbox'));
70-
71-
expect($rootScope.modelVal).toBeFalsy();
72-
checkbox.triggerHandler({
73-
type: 'keypress',
74-
keyCode: $mdConstant.KEY_CODE.SPACE
75-
});
76-
expect($rootScope.modelVal).toBe(true);
68+
var listItem = setup('<md-list-item><md-checkbox ng-model="modelVal"></md-checkbox></md-list-item>');
69+
var checkbox = angular.element(listItem[0].querySelector('md-checkbox'));
70+
71+
expect($rootScope.modelVal).toBeFalsy();
72+
checkbox.triggerHandler({
73+
type: 'keypress',
74+
keyCode: $mdConstant.KEY_CODE.SPACE
75+
});
76+
expect($rootScope.modelVal).toBe(true);
7777
}));
7878

7979
it('should not convert spacebar keypress for text areas', inject(function($mdConstant) {
80-
var listItem = setup('<md-list-item><textarea ng-model="modelVal"></md-list-item>');
81-
var inputEl = angular.element(listItem[0].querySelector('textarea')[0]);
82-
83-
expect($rootScope.modelVal).toBeFalsy();
84-
inputEl.triggerHandler({
85-
type: 'keypress',
86-
keyCode: $mdConstant.KEY_CODE.SPACE
87-
});
88-
expect($rootScope.modelVal).toBeFalsy();
80+
var listItem = setup('<md-list-item><textarea ng-model="modelVal"></md-list-item>');
81+
var inputEl = angular.element(listItem[0].querySelector('textarea')[0]);
82+
83+
expect($rootScope.modelVal).toBeFalsy();
84+
inputEl.triggerHandler({
85+
type: 'keypress',
86+
keyCode: $mdConstant.KEY_CODE.SPACE
87+
});
88+
expect($rootScope.modelVal).toBeFalsy();
8989
}));
9090

9191
xit('should not convert spacebar keypress for text inputs', inject(function($mdConstant) {
9292

93-
var listItem = setup('<md-list-item><input ng-keypress="pressed = true" type="text"></md-list-item>');
94-
var inputEl = angular.element(listItem[0].querySelector('input')[0]);
93+
var listItem = setup('<md-list-item><input ng-keypress="pressed = true" type="text"></md-list-item>');
94+
var inputEl = angular.element(listItem[0].querySelector('input')[0]);
9595

96-
expect($rootScope.pressed).toBeFalsy();
97-
inputEl.triggerHandler({
98-
type: 'keypress',
99-
keyCode: $mdConstant.KEY_CODE.SPACE
100-
});
101-
expect($rootScope.pressed).toBe(true);
96+
expect($rootScope.pressed).toBeFalsy();
97+
inputEl.triggerHandler({
98+
type: 'keypress',
99+
keyCode: $mdConstant.KEY_CODE.SPACE
100+
});
101+
expect($rootScope.pressed).toBe(true);
102102
}));
103103

104104

@@ -157,6 +157,21 @@ describe('mdListItem directive', function() {
157157
expect(listItem.hasClass('md-no-proxy')).toBeTruthy();
158158
});
159159

160+
it('should copy md-icon.md-secondary attributes to the button', function() {
161+
var listItem = setup(
162+
'<md-list-item>' +
163+
' <div>Content Here</div>' +
164+
' <md-checkbox></md-checkbox>' +
165+
' <md-icon class="md-secondary" ng-click="sayHello()" ng-disabled="true">Hello</md-icon>' +
166+
'</md-list-item>'
167+
);
168+
169+
var button = listItem.find('md-button');
170+
171+
expect(button[0].hasAttribute('ng-click')).toBeTruthy();
172+
expect(button[0].hasAttribute('ng-disabled')).toBeTruthy();
173+
});
174+
160175
describe('with a clickable item', function() {
161176

162177
it('should wrap secondary icons in a md-button', function() {

0 commit comments

Comments
 (0)