AngularJS Dynamic Form Validation

Add required attribute dynamically to angular form field

by Tarek Faham

HTML

<form name="myForm" ng-app="form-example" class="row form-horizontal" novalidate>
 <div class="control-group" ng-form="testReq">
     <h3>Form invalid: {{testReq.$invalid}}</h3>
  <label class="control-label" for="inputEmail">Email</label>
  <div class="controls">
    <input id="inputEmail" name="email1" placeholder="Any text" ng-model="email" requireiftrue="true" type="text">
    <input id="inputEmail2" name="email2" placeholder="Email" ng-model="email2" type="email" requireiftrue="false">

  </div>
 </div>
<div class="control-group">
  <div class="controls">
    <button type="submit" class="btn" ng-disabled="testReq.$invalid">Create Account</button>
    <br>
    <pre>
      {{myForm.testReq.email2 | json}}
    </pre>
  </div>
 </div>
</form>

CSS

.input-help {
  display: none;
  position:absolute;
  z-index: 100;
  top: -6px;
  left: 160px;
  width:200px;
  padding:10px;
  background:#fefefe;
  font-size:.875em;
  border-radius:5px;
  box-shadow:0 1px 3px #aaa;
  border:1px solid #ddd;
  opacity: 0.9;
}
.input-help::before {
  content: "\25C0";
  position: absolute;
  top:10px;
  left:-12px;
  font-size:16px;
  line-height:16px;
  color:#ddd;
  text-shadow:none;
}
.input-help h4 {
  margin:0;
  padding:0;
  font-weight: normal;
  font-size: 1.1em;
}

/* Always hide the input help when it's pristine */
input.ng-pristine + .input-help {
  display: none;
}

/* Hide the invalid box while the input has focus */
.ng-invalid:focus + .input-help {
  display: none;
}

/* Show a blue border while an input has focus, make sure it overrides everything else */
/* Overriding Twitter Bootstrap cuz I don't agree we need to alarm the user while they're typing */
input:focus {
  color: black !important;
  border-color: rgba(82, 168, 236, 0.8) !important;
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) !important;
  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) !important;
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) !important;
}


/* Show green border when stuff has been typed in, and its valid */
.ng-dirty.ng-valid {
  border-color:#3a7d34;
}

/* Show red border when stuff has been typed in, but its invalid */
.ng-dirty.ng-invalid {
  border-color:#ec3f41;
}

/* Show the help box once it has focus */
.immediate-help:focus + .input-help {
  display: block;
}

/* Immediate help should be red when pristine */
.immediate-help.ng-pristine:focus + .input-help {
  border-color:#ec3f41;
}
.immediate-help.ng-pristine:focus + .input-help::before {
  color:#ec3f41;
}

/* Help hould be green when input is valid */
.ng-valid + .input-help {
  border-color:#3a7d34;
}
.ng-valid + .input-help::before {
 ...

JavaScript

var app = angular.module('form-example', []);

app.directive('requireiftrue', function ($compile) {
    return {
        require: '?ngModel',
        link: function (scope, el, attrs, ngModel) {
        	debugger;
            if (!ngModel) {
                return;
            }

						//Check if element name is in the list of required fields,
            //and add the required attribute accordingly.
            if(attrs.requireiftrue==="true"){
                console.log('should require');
                el.attr('required', true);
                el.removeAttr('requireiftrue');
                $compile(el[0])(scope);
            }
            else{
                console.log('should not require');   
            }
        }
    };
});