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);
  }

};