AngularJS Live Example
by Mirosław Hajkowski
HTML
<script src="http://docs-next.angularjs.org/angular-0.10.6.min.js"></script>
<script src="http://code.angularjs.org/angular-0.10.6.min.js"></script>
<script src="http://code.angularjs.org/angular-0.10.6.min.js"></script>
<script src="http://code.angularjs.org/angular-0.10.6.min.js"></script>
<div ng:app>
<div ng:controller="UserFormCntl">
<form name="userForm">
<label>Name:</label><br/>
<input type="text" name="customer" ng:model="form.customer" required/>
<span class="error" ng:show="userForm.customer.$error.REQUIRED">
Customer name is required!</span>
<br/><br/>
<ng:form name="addressForm">
<label>Address:</label> <br/>
<input type="text" name="line1" size="33" required
ng:model="form.address.line1"/> <br/>
<input type="text" name="city" size="12" required
ng:model="form.address.city"/>,
<input type="text" name="state" ng:pattern="state" size="2" required
ng:model="form.address.state"/>
<input type="text" name="zip" ng:pattern="zip" size="5" required
ng:model="form.address.zip"/><br/><br/>
<span class="error" ng:show="addressForm.$invalid">
Incomplete address:
<span class="error" ng:show="addressForm.state.$error.REQUIRED">
Missing state!</span>
<span class="error" ng:show="addressForm.state.$error.PATTERN">
Invalid state!</span>
<span class="error" ng:show="addressForm.zip.$error.REQUIRED">
Missing zip!</span>
<span class="error" ng:show="addressForm.zip.$error.PATTERN">
Invalid zip!</span>
</span>
</ng:form>
<button ng:click="cancel()"
ng:disabled="{{isCancelDisabled()}}">Cancel</button>
<button ng:click="save()"
ng:disabled="{{isSaveDisabled()}}">Save</button>
</form>
<hr/>
Debug View:
<pre>form={{form}}</pre>
<pre>master={{master}}</pre>
...
CSS
.ng-form {display: block;}
input.ng-invalid.ng-dirty { border: solid 1px red; }
.ng-pristine + .error { display: none}
body { font-family: Arial,Helvetica,sans-serif; }
body, td, th { font-size: 14px; margin: 0; }
table { border-collapse: separate; border-spacing: 2px; display: table; margin-bottom: 0; margin-top: 0; -moz-box-sizing: border-box; text-indent: 0; }
a:link, a:visited, a:hover { color: #5D6DB6; text-decoration: none; }
.error { color: red; }
JavaScript
function UserFormCntl() {
this.state = /^\w\w$/;
this.zip = /^\d\d\d\d\d$/;
this.master = {
customer: '',
address:{
line1: '123 Main St.',
city:'Anytown',
state:'AA',
zip:'12345'
}
};
this.cancel();
}
UserFormCntl.prototype = {
cancel: function() {
this.form = angular.copy(this.master);
},
save: function() {
this.master = this.form;
this.cancel();
},
isCancelDisabled: function() {
return angular.equals(this.master, this.form);
},
isSaveDisabled: function() {
return this.userForm.$invalid || angular.equals(this.master, this.form);
}
};