@@ -97,6 +97,24 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $
97
97
var containerCtrl = ctrls [ 0 ] ;
98
98
var ngModelCtrl = ctrls [ 1 ] || $mdUtil . fakeNgModel ( ) ;
99
99
var formCtrl = ctrls [ 2 ] ;
100
+ var labelHasLink = element . find ( 'a' ) . length > 0 ;
101
+
102
+ // The original component structure is not accessible when the checkbox's label contains a link.
103
+ // In order to keep backwards compatibility, we're only changing the structure of the component
104
+ // when we detect a link within the label. Using a span after the md-checkbox and attaching it
105
+ // via aria-labelledby allows screen readers to find and work with the link within the label.
106
+ if ( labelHasLink ) {
107
+ var labelId = 'label-' + $mdUtil . nextUid ( ) ;
108
+ attr . $set ( 'aria-labelledby' , labelId ) ;
109
+
110
+ var label = element . children ( ) [ 1 ] ;
111
+ var labelContents = label . innerHTML ;
112
+ label . remove ( ) ;
113
+ element . after ( '<span id="' + labelId + '" class="md-checkbox-link-label">' + labelContents + '</span>' ) ;
114
+ // Make sure that clicking on the label still causes the checkbox to be toggled, when appropriate.
115
+ var externalLabel = element . next ( ) ;
116
+ externalLabel . on ( 'click' , listener ) ;
117
+ }
100
118
101
119
if ( containerCtrl ) {
102
120
var isErrorGetter = containerCtrl . isErrorGetter || function ( ) {
@@ -133,7 +151,11 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $
133
151
false : attr . tabindex
134
152
} ) ;
135
153
136
- $mdAria . expectWithText ( element , 'aria-label' ) ;
154
+ // Don't emit a warning when the label has a link within it. In that case we'll use
155
+ // aria-labelledby to point to another span that should be read as the label.
156
+ if ( ! labelHasLink ) {
157
+ $mdAria . expectWithText ( element , 'aria-label' ) ;
158
+ }
137
159
138
160
// Reuse the original input[type=checkbox] directive from AngularJS core.
139
161
// This is a bit hacky as we need our own event listener and own render
@@ -177,8 +199,10 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $
177
199
178
200
function listener ( ev ) {
179
201
// skipToggle boolean is used by the switch directive to prevent the click event
180
- // when releasing the drag. There will be always a click if releasing the drag over the checkbox
181
- if ( element [ 0 ] . hasAttribute ( 'disabled' ) || scope . skipToggle ) {
202
+ // when releasing the drag. There will be always a click if releasing the drag over the checkbox.
203
+ // If the click came from a link in the checkbox, don't toggle the value.
204
+ // We want the link to be opened without changing the value in this case.
205
+ if ( element [ 0 ] . hasAttribute ( 'disabled' ) || scope . skipToggle || ev . target . tagName === 'A' ) {
182
206
return ;
183
207
}
184
208
0 commit comments