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

docs(input): better accessibility in examples #11079

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -621,8 +621,8 @@
}]);
</script>
<div ng-controller="GreeterController">
<input ng-model="name"> <br>
<textarea ng-model="html"></textarea> <br>
<input ng-model="name"> <br/>
<textarea ng-model="html"></textarea> <br/>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should have labels too. Oops! I'll fix them up later.

<div compile="html"></div>
</div>
</file>
Expand Down Expand Up @@ -659,7 +659,7 @@
* * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
* `template` and call the `cloneAttachFn` function allowing the caller to attach the
* cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
* called as: <br> `cloneAttachFn(clonedElement, scope)` where:
* called as: <br/> `cloneAttachFn(clonedElement, scope)` where:
*
* * `clonedElement` - is a clone of the original `element` passed into the compiler.
* * `scope` - is the current scope with which the linking function is working with.
Expand Down
24 changes: 12 additions & 12 deletions src/ng/directive/attrs.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@
*
* The buggy way to write it:
* ```html
* <img src="http://www.gravatar.com/avatar/{{hash}}"/>
* <img src="http://www.gravatar.com/avatar/{{hash}}" alt="Description"/>
* ```
*
* The correct way to write it:
* ```html
* <img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
* <img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* ```
*
* @element IMG
Expand All @@ -139,12 +139,12 @@
*
* The buggy way to write it:
* ```html
* <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
* <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description"/>
* ```
*
* The correct way to write it:
* ```html
* <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
* <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest the same change is made to the buggy way above.
Since this example is about src vs ngSrc, we don't want to distract the reader into thinking alt has anything to do with that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. That makes sense to me.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gkalpak @marcysutton why not add the alt to both?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Great suggestion.

* ```
*
* @element IMG
Expand Down Expand Up @@ -181,7 +181,7 @@
* @example
<example>
<file name="index.html">
Click me to toggle: <input type="checkbox" ng-model="checked"><br/>
<label>Click me to toggle: <input type="checkbox" ng-model="checked"></label><br/>
<button ng-model="button" ng-disabled="checked">Button</button>
</file>
<file name="protractor.js" type="protractor">
Expand Down Expand Up @@ -216,8 +216,8 @@
* @example
<example>
<file name="index.html">
Check me to check both: <input type="checkbox" ng-model="master"><br/>
<input id="checkSlave" type="checkbox" ng-checked="master">
<label>Check me to check both: <input type="checkbox" ng-model="master"></label><br/>
<input id="checkSlave" type="checkbox" ng-checked="master" aria-label="Slave input">
</file>
<file name="protractor.js" type="protractor">
it('should check both checkBoxes', function() {
Expand Down Expand Up @@ -251,8 +251,8 @@
* @example
<example>
<file name="index.html">
Check me to make text readonly: <input type="checkbox" ng-model="checked"><br/>
<input type="text" ng-readonly="checked" value="I'm Angular"/>
<label>Check me to make text readonly: <input type="checkbox" ng-model="checked"></label><br/>
<input type="text" ng-readonly="checked" value="I'm Angular" aria-label="Readonly field" />
</file>
<file name="protractor.js" type="protractor">
it('should toggle readonly attr', function() {
Expand Down Expand Up @@ -287,8 +287,8 @@
* @example
<example>
<file name="index.html">
Check me to select: <input type="checkbox" ng-model="selected"><br/>
<select>
<label>Check me to select: <input type="checkbox" ng-model="selected"></label><br/>
<select aria-label="ngSelected demo">
<option>Hello!</option>
<option id="greet" ng-selected="selected">Greetings!</option>
</select>
Expand Down Expand Up @@ -324,7 +324,7 @@
* @example
<example>
<file name="index.html">
Check me check multiple: <input type="checkbox" ng-model="open"><br/>
<label>Check me check multiple: <input type="checkbox" ng-model="open"></label><br/>
<details id="details" ng-open="open">
<summary>Show/Hide me</summary>
</details>
Expand Down
196 changes: 123 additions & 73 deletions src/ng/directive/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,16 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="ExampleController">
Single word: <input type="text" name="input" ng-model="example.text"
ng-pattern="example.word" required ng-trim="false">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.pattern">
Single word only!</span>

<label>Single word:
<input type="text" name="input" ng-model="example.text"
ng-pattern="example.word" required ng-trim="false">
</label>
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.pattern">
Single word only!</span>
</div>
<tt>text = {{example.text}}</tt><br/>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
Expand Down Expand Up @@ -153,13 +156,15 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="DateController as dateCtrl">
Pick a date in 2013:
<label for="exampleInput">Pick a date in 2013:</label>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like exampleInput is a duplicate id. Will that impact focus and AT behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It normally would, but it's isolated to this one demo: https://docs.angularjs.org/api/ng/input/input%5Bdate%5D. They show up on different pages (date and datetime-local).

<input type="date" id="exampleInput" name="input" ng-model="example.value"
placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.date">
Not a valid date!</span>
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.date">
Not a valid date!</span>
</div>
<tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
Expand Down Expand Up @@ -246,13 +251,15 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="DateController as dateCtrl">
Pick a date between in 2013:
<label for="exampleInput">Pick a date between in 2013:</label>
<input type="datetime-local" id="exampleInput" name="input" ng-model="example.value"
placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required />
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.datetimelocal">
Not a valid date!</span>
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.datetimelocal">
Not a valid date!</span>
</div>
<tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
Expand Down Expand Up @@ -340,13 +347,15 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="DateController as dateCtrl">
Pick a between 8am and 5pm:
<label for="exampleInput">Pick a between 8am and 5pm:</label>
<input type="time" id="exampleInput" name="input" ng-model="example.value"
placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required />
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.time">
Not a valid date!</span>
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.time">
Not a valid date!</span>
</div>
<tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
Expand Down Expand Up @@ -433,13 +442,17 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="DateController as dateCtrl">
Pick a date between in 2013:
<input id="exampleInput" type="week" name="input" ng-model="example.value"
placeholder="YYYY-W##" min="2012-W32" max="2013-W52" required />
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.week">
Not a valid date!</span>
<label>Pick a date between in 2013:
<input type="week" name="input" ng-model="example.value"
placeholder="YYYY-W##" min="2012-W32"
max="2013-W52" required />
</label>
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.week">
Not a valid date!</span>
</div>
<tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
Expand Down Expand Up @@ -526,13 +539,15 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="DateController as dateCtrl">
Pick a month in 2013:
<label for="exampleInput">Pick a month in 2013:</label>
<input id="exampleInput" type="month" name="input" ng-model="example.value"
placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.month">
Not a valid month!</span>
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.month">
Not a valid month!</span>
</div>
<tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
Expand Down Expand Up @@ -629,12 +644,16 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="ExampleController">
Number: <input type="number" name="input" ng-model="example.value"
min="0" max="99" required>
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.number">
Not valid number!</span>
<label>Number:
<input type="number" name="input" ng-model="example.value"
min="0" max="99" required>
</label>
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.number">
Not valid number!</span>
</div>
<tt>value = {{example.value}}</tt><br/>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
Expand Down Expand Up @@ -719,11 +738,15 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="ExampleController">
URL: <input type="url" name="input" ng-model="url.text" required>
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.url">
Not valid url!</span>
<label>URL:
<input type="url" name="input" ng-model="url.text" required>
<label>
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.url">
Not valid url!</span>
</div>
<tt>text = {{url.text}}</tt><br/>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
Expand Down Expand Up @@ -810,11 +833,15 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="ExampleController">
Email: <input type="email" name="input" ng-model="email.text" required>
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.email">
Not valid email!</span>
<label>Email:
<input type="email" name="input" ng-model="email.text" required>
</label>
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.email">
Not valid email!</span>
</div>
<tt>text = {{email.text}}</tt><br/>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
Expand Down Expand Up @@ -883,9 +910,18 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="ExampleController">
<input type="radio" ng-model="color.name" value="red"> Red <br/>
<input type="radio" ng-model="color.name" ng-value="specialValue"> Green <br/>
<input type="radio" ng-model="color.name" value="blue"> Blue <br/>
<label>
<input type="radio" ng-model="color.name" value="red">
Red
</label><br/>
<label>
<input type="radio" ng-model="color.name" ng-value="specialValue">
Green
</label><br/>
<label>
<input type="radio" ng-model="color.name" value="blue">
Blue
</label><br/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add ids, if are nesting them into labels ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, that was leftover from my first pass on the code. They are no longer necessary!

<tt>color = {{color.name | json}}</tt><br/>
</form>
Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
Expand Down Expand Up @@ -933,9 +969,13 @@ var inputType = {
}]);
</script>
<form name="myForm" ng-controller="ExampleController">
Value1: <input type="checkbox" ng-model="checkboxModel.value1"> <br/>
Value2: <input type="checkbox" ng-model="checkboxModel.value2"
ng-true-value="'YES'" ng-false-value="'NO'"> <br/>
<label>Value1:
<input type="checkbox" ng-model="checkboxModel.value1">
</label><br/>
<label>Value2:
<input type="checkbox" ng-model="checkboxModel.value2"
ng-true-value="'YES'" ng-false-value="'NO'">
</label><br/>
<tt>value1 = {{checkboxModel.value1}}</tt><br/>
<tt>value2 = {{checkboxModel.value2}}</tt><br/>
</form>
Expand Down Expand Up @@ -1452,26 +1492,36 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt
</script>
<div ng-controller="ExampleController">
<form name="myForm">
User name: <input type="text" name="userName" ng-model="user.name" required>
<span class="error" ng-show="myForm.userName.$error.required">
Required!</span><br>
Last name: <input type="text" name="lastName" ng-model="user.last"
ng-minlength="3" ng-maxlength="10">
<span class="error" ng-show="myForm.lastName.$error.minlength">
Too short!</span>
<span class="error" ng-show="myForm.lastName.$error.maxlength">
Too long!</span><br>
<label>
User name:
<input type="text" name="userName" ng-model="user.name" required>
</label>
<div role="alert">
<span class="error" ng-show="myForm.userName.$error.required">
Required!</span>
</div>
<label>
Last name:
<input type="text" name="lastName" ng-model="user.last"
ng-minlength="3" ng-maxlength="10">
</label>
<div role="alert">
<span class="error" ng-show="myForm.lastName.$error.minlength">
Too short!</span>
<span class="error" ng-show="myForm.lastName.$error.maxlength">
Too long!</span>
</div>
</form>
<hr>
<tt>user = {{user}}</tt><br/>
<tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>
<tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>
<tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>
<tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>
<tt>myForm.$valid = {{myForm.$valid}}</tt><br>
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
<tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>
<tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>
<tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br/>
<tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br/>
<tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br/>
<tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br/>
<tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
<tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br/>
<tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br/>
</div>
</file>
<file name="protractor.js" type="protractor">
Expand Down
Loading