@@ -36,14 +36,21 @@ include ../_util-fns
36
36
37
37
.l-sub-section
38
38
:marked
39
- Use this method to label your `form controls` as far as possible. As you will see later the other methods of
40
- labelling relies on generating unique id's for your elements. And as we are often building re-usable components
41
- in Angular 2, you will need to insure that every id you create is unique on a page, no matter how often your
42
- component is used! Save yourself the trouble and label implicitly.
39
+ `ARIA`, or `Accessible Rich Internet Applications` refers to bringing `a11y` concepts into
40
+ internet applications like those we are building with Angular 2.
43
41
44
42
:marked
45
43
You can also see what they say about [ARIA](https://www.w3.org/WAI/intro/aria) at the `W3C`. We will be right here
46
44
waiting for you when you come back.
45
+
46
+ .callout.is-important
47
+ header ARIA terminology confusion alert!
48
+ :marked
49
+ In `ARIA` we refer to the `aria-...` attributes as `ARIA States` or `ARIA Properties`. The difference between
50
+ the two should become clear as you progress through this cookbook. However, `ARIA Properties` are not
51
+ actual `HTML` element properties but decorating attributes refering to properties. When we refer to setting an
52
+ `ARIA Property` in the code you will **HAVE** to do
53
+ it with an Angular 2 attribute binding. This is simply a terminology clash.
47
54
48
55
.l-main-section
49
56
:marked
@@ -107,6 +114,12 @@ include ../_util-fns
107
114
108
115
[Managing focus](#managin-focus)
109
116
117
+ .l-sub-section
118
+ :marked
119
+ In the example application code when we require unique element id's we will be generating `GUID's`to ensure that they are
120
+ unique. You can use your own method to do this, as long as every id on a page is unique. More on this later...
121
+
122
+ :marked
110
123
**Feel free to follow along in this [live example](/resources/live-examples/cb-a11y/ts/plnkr.html)**.
111
124
112
125
.l-main-section
@@ -277,46 +290,86 @@ code-example(language="html" escape="html").
277
290
:marked
278
291
### Labelling custom form controls
279
292
280
- So you have been asked to do something and try as you might you cannot find a native `HTML` element to do the job
281
- **OR** you are want to give that legacy application an `a11y` makeover without having the luxury to rewrite the
293
+ So you have been asked to do something and try as you might you cannot construct this with native `HTML` elements
294
+ **OR** you are want to give that legacy application an `a11y` makeover without the luxury of rewriting the
282
295
entire codebase.
283
296
284
297
How would you go about making these custom form controls accessible?
285
298
286
- Fear not, there is a way!
287
-
288
- To avoid writing many lines of code as an example we will create an input field out of a `div`. Rest assured,
289
- not using the native `HTML` elements in practise will cost a lot more code than this to make it fully functional.
290
- Everytime you bend this rule your codebase will grow and become more complex.
291
-
292
- Component template:
299
+ Fear not, there is a way! We introduce the next addition to our `ARIA` toolkit, and that is `aria-labeledby`.
300
+
301
+ Why do we need this? Because the native `a11y` function of the `label` element is only recognised when used with
302
+ native `HTML` form control elements such as `input` and `textarea`. To label anything else, like a `div` or a
303
+ `custom element` we need to create the the link using `aria-labelledby`.
304
+
305
+ Lets illustrate this by recreating the native `input` element with a component that makes use of `div's`.
306
+
307
+ .l-sub-section
308
+ :marked
309
+ Please note that creating an `input` out of `div's` is **NOT** recommended, but only serves as an illustration that
310
+ it is possible to make any form controll accessible. And as we are focussing on `a11y`, our component will also not
311
+ be production ready but only
312
+ implement the basics of functionality to make it function as an `input` i.e. adding the machinery to make it play nice
313
+ with `ngModel`. This implementation would need to become
314
+ even larger and more complex before it can be used in an enterprise application. We hope that this illustrates
315
+ further why the native `HTML` elements should preferably be used.
316
+
317
+ :marked
318
+ Our component:
293
319
294
- + makeExample('cb-a11y/ts/app/form-controls/a11y-custom-control.component.html' )
320
+ + makeTabs('cb-a11y/ts/app/form-controls/a11y-custom-control.component.html,cb-a11y/ts/app/form-controls/a11y-custom-control.component.ts,cb-a11y/ts/app/form-controls/a11y-custom-control.component.css' ,
321
+ null , 'a11y-custom-control.component.html,a11y-custom-control.component.ts, a11y-custom-control.component.css' )
295
322
296
323
:marked
297
- User writes :
324
+ This can now be used in our `HTML` as follows :
298
325
299
326
+ makeExample('cb-a11y/ts/app/form-controls/a11y-form-controls.component.html' ,'cb-a11y-form-controls-custom-control-usage' )
300
327
301
328
:marked
302
- Rendered out:
329
+ Lets have a look at what is rendered out. *For clarity sake, the style attributes added by Angular 2 for the component
330
+ style have been omitted.*:
303
331
304
332
code-example( language ="html" escape ="html" format ="linenums" ) .
305
- <a11y-custom-control >
333
+ <a11y-custom-control class = " ng-pristine ng-valid ng-untouched " >
306
334
<div class =" form-group" >
307
- <label id =" 9db87459-2e0d-49ea-a8bf-bb7a3a599858 " >
335
+ <label id =" 60e9545d-8c5c-4c55-f171-e266c50479e9 " >
308
336
Write in this labelled div:
309
337
</label >
310
- <div class =" form-control" contenteditable =" " role =" textbox" aria-labelledby =" 9db87459-2e0d-49ea-a8bf-bb7a3a599858" ></div >
338
+ < div aria-multiline="true" class="form-control edit-box" contenteditable=""
339
+ role="textbox" aria-labelledby="60e9545d-8c5c-4c55-f171-e266c50479e9"> </div >
311
340
</div >
312
341
</a11y-custom-control >
313
342
343
+ :marked
344
+ The first thing that we should note is the `role` attribute. This is also part of `ARIA` and we use these when we need
345
+ to tell assistive technologies the functional role a component has. We need to specify this when we are not using the
346
+ native `HTML` elements. For those elements the role is already defined. Here, our custom control needs the role of
347
+ `textarea`. We will look at `ARIA Roles` in more detail later.
348
+
349
+ Next we will look at the `aria-labelledby` attribute. As you can see this contains the `id` of the `label` field. This
350
+ is how we tell screen readers to use that specific `label` element to label our input control.
351
+
314
352
.l-sub-section
315
353
:marked
316
- In the example application code we are generating `GUID's` for id's to ensure that they are unique. You can use your
317
- own method to do this, as long as every id on a page is unique.
318
-
319
-
354
+ Aside from having to generate unique `id's`, there is one more caveat to using `aria-labelledby`. Even when using this
355
+ with an actual `label` element, clicking the label will **NOT** focus the input as it does when used with native
356
+ `HTML` form control elements. Therefore this construct will always be slightly inferior to the native approach, as you lose the
357
+ accessibility gain the `label click` gives you.
358
+
359
+ :marked
360
+ And finally, while you were not looking we snuck in yet another `ARIA` property called `aria-multiline`. Yes folks,
361
+ someone unable to see what is happening also needs to know if our input accepts single or multiple lines of input. Using
362
+ `aria-multiline`, we are able to tell the screan reader if it is single or multiline and the screen reader will even
363
+ read this information back to the user.
364
+
365
+ That was certainly a mouthful! Isn't there a middle way where we can use the power of Angular 2 but keep the
366
+ built-in `a11y` wins the native `HTML` elements give us?
367
+
368
+ There certainly are. Let's look at one option that uses `Content Projection`.
369
+
370
+
371
+
372
+
320
373
.l-main-section
321
374
<a id =" keyboard-shortcuts" ></a >
322
375
:marked
@@ -336,4 +389,4 @@ code-example(language="html" escape="html" format="linenums").
336
389
:marked
337
390
## Managing focus
338
391
339
- Content coming soon...r
392
+ Content coming soon...
0 commit comments