@@ -27,8 +27,8 @@ for other directives to augment its behavior.
2727 E-mail: <input type="email" ng-model="user.email" /><br />
2828 Gender: <input type="radio" ng-model="user.gender" value="male" />male
2929 <input type="radio" ng-model="user.gender" value="female" />female<br />
30- <button ng-click="reset()">RESET</button >
31- <button ng-click="update(user)">SAVE</button >
30+ <input type=" button" ng-click="reset()" value="Reset" / >
31+ <input type="submit" ng-click="update(user)" value="Save" / >
3232 </form>
3333 <pre>form = {{user | json}}</pre>
3434 <pre>master = {{master | json}}</pre>
@@ -77,29 +77,29 @@ To allow styling of form as well as controls, `ngModel` adds these CSS classes:
7777
7878The following example uses the CSS to display validity of each form control.
7979In the example both `user.name` and `user.email` are required, but are rendered
80- with red background only when they are dirty. This ensures that the user is not distracted
81- with an error until after interacting with the control, and failing to satisfy its validity.
80+ with red background only after the input is blurred (loses focus).
81+ This ensures that the user is not distracted with an error until after interacting with the control,
82+ and failing to satisfy its validity.
8283
8384<example module="formExample">
8485 <file name="index.html">
8586 <div ng-controller="ExampleController">
8687 <form novalidate class="css-form">
87- Name:
88- <input type="text" ng-model="user.name" required /><br />
88+ Name: <input type="text" ng-model="user.name" required /><br />
8989 E-mail: <input type="email" ng-model="user.email" required /><br />
9090 Gender: <input type="radio" ng-model="user.gender" value="male" />male
9191 <input type="radio" ng-model="user.gender" value="female" />female<br />
92- <button ng-click="reset()">RESET</button >
93- <button ng-click="update(user)">SAVE</button >
92+ <input type=" button" ng-click="reset()" value="Reset" / >
93+ <input type="submit" ng-click="update(user)" value="Save" / >
9494 </form>
9595 </div>
9696
9797 <style type="text/css">
98- .css-form input.ng-invalid.ng-dirty {
98+ .css-form input.ng-invalid.ng-touched {
9999 background-color: #FA787E;
100100 }
101101
102- .css-form input.ng-valid.ng-dirty {
102+ .css-form input.ng-valid.ng-touched {
103103 background-color: #78FA89;
104104 }
105105 </style>
@@ -140,34 +140,45 @@ the view using the standard binding primitives.
140140
141141This allows us to extend the above example with these features:
142142
143- - RESET button is enabled only if form has some changes
144- - SAVE button is enabled only if form has some changes and is valid
145- - custom error messages for `user.email` and `user.agree`
143+ - Custom error message displayed after the user interacted with a control (i.e. when `$touched` is set)
144+ - Custom error message displayed upon submitting the form (`$submitted` is set), even if the user
145+ didn't interact with a control
146+
146147
147148<example module="formExample">
148149 <file name="index.html">
149150 <div ng-controller="ExampleController">
150151 <form name="form" class="css-form" novalidate>
151152 Name:
152- <input type="text" ng-model="user.name" name="uName" required /><br />
153+ <input type="text" ng-model="user.name" name="uName" required="" />
154+ <br />
155+ <div ng-show="form.$submitted || form.uName.$touched">
156+ <div ng-show="form.uName.$error.required">Tell us your name.</div>
157+ </div>
158+
153159 E-mail:
154- <input type="email" ng-model="user.email" name="uEmail" required/><br />
155- <div ng-show="form.uEmail.$dirty && form.uEmail.$invalid">Invalid:
160+ <input type="email" ng-model="user.email" name="uEmail" required="" />
161+ <br />
162+ <div ng-show="form.$submitted || form.uEmail.$touched">
156163 <span ng-show="form.uEmail.$error.required">Tell us your email.</span>
157164 <span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
158165 </div>
159166
160- Gender: <input type="radio" ng-model="user.gender" value="male" />male
161- <input type="radio" ng-model="user.gender" value="female" />female<br />
162-
163- <input type="checkbox" ng-model="user.agree" name="userAgree" required />
164- I agree: <input ng-show="user.agree" type="text" ng-model="user.agreeSign"
165- required /><br />
166- <div ng-show="!user.agree || !user.agreeSign">Please agree and sign.</div>
167+ Gender:
168+ <input type="radio" ng-model="user.gender" value="male" />male
169+ <input type="radio" ng-model="user.gender" value="female" />female
170+ <br />
171+ <input type="checkbox" ng-model="user.agree" name="userAgree" required="" />
172+
173+ I agree:
174+ <input ng-show="user.agree" type="text" ng-model="user.agreeSign" required="" />
175+ <br />
176+ <div ng-show="form.$submitted || form.userAgree.$touched">
177+ <div ng-show="!user.agree || !user.agreeSign">Please agree and sign.</div>
178+ </div>
167179
168- <button ng-click="reset()" ng-disabled="isUnchanged(user)">RESET</button>
169- <button ng-click="update(user)"
170- ng-disabled="form.$invalid || isUnchanged(user)">SAVE</button>
180+ <input type="button" ng-click="reset(form)" value="Reset" />
181+ <input type="submit" ng-click="update(user)" value="Save" />
171182 </form>
172183 </div>
173184 </file>
@@ -181,14 +192,14 @@ This allows us to extend the above example with these features:
181192 $scope.master = angular.copy(user);
182193 };
183194
184- $scope.reset = function() {
195+ $scope.reset = function(form) {
196+ if (form) {
197+ form.$setPristine();
198+ form.$setUntouched();
199+ }
185200 $scope.user = angular.copy($scope.master);
186201 };
187202
188- $scope.isUnchanged = function(user) {
189- return angular.equals(user, $scope.master);
190- };
191-
192203 $scope.reset();
193204 }]);
194205 </file>
0 commit comments