@@ -36,14 +36,21 @@ include ../_util-fns
3636
3737.l-sub-section
3838 :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.
4341
4442:marked
4543 You can also see what they say about [ARIA](https://www.w3.org/WAI/intro/aria) at the `W3C`. We will be right here
4644 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.
4754
4855.l-main-section
4956:marked
@@ -107,6 +114,12 @@ include ../_util-fns
107114
108115 [Managing focus](#managin-focus)
109116
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
110123 **Feel free to follow along in this [live example](/resources/live-examples/cb-a11y/ts/plnkr.html)**.
111124
112125.l-main-section
@@ -277,46 +290,86 @@ code-example(language="html" escape="html").
277290:marked
278291 ### Labelling custom form controls
279292
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
282295 entire codebase.
283296
284297 How would you go about making these custom form controls accessible?
285298
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:
293319
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' )
295322
296323:marked
297- User writes :
324+ This can now be used in our `HTML` as follows :
298325
299326+ makeExample('cb-a11y/ts/app/form-controls/a11y-form-controls.component.html' ,'cb-a11y-form-controls-custom-control-usage' )
300327
301328: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.*:
303331
304332code-example( language ="html" escape ="html" format ="linenums" ) .
305- <a11y-custom-control >
333+ <a11y-custom-control class = " ng-pristine ng-valid ng-untouched " >
306334 <div class =" form-group" >
307- <label id =" 9db87459-2e0d-49ea-a8bf-bb7a3a599858 " >
335+ <label id =" 60e9545d-8c5c-4c55-f171-e266c50479e9 " >
308336 Write in this labelled div:
309337 </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 >
311340 </div >
312341 </a11y-custom-control >
313342
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+
314352.l-sub-section
315353 :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+
320373.l-main-section
321374<a id =" keyboard-shortcuts" ></a >
322375:marked
@@ -336,4 +389,4 @@ code-example(language="html" escape="html" format="linenums").
336389:marked
337390 ## Managing focus
338391
339- Content coming soon...r
392+ Content coming soon...
0 commit comments