AngularJS Validation

This is a demonstration of how to modify the typical validation routine of angular as well as demonstrate the handling of HTML5 elements.

by manoj

HTML

<script src="http://code.angularjs.org/1.0.7/angular.min.js"></script>
<form name="myForm" novalidate>
    <ul ng-controller="Fiddle">
        <li>
            <label for="foobar">Number Input</label>
            <input id="foobar" name="foobar" type="text" ng-model="foo" ng-pattern="/[0-9]/" required />
            <span class="error-message" ng-show="!myForm.foobar.hasFocus && myForm.foobar.hasVisited && myForm.foobar.$error.pattern">This field must be a number.<!-- This bit does not work in Chrome --></span>
            <span class="error-message" ng-show="!myForm.foobar.hasFocus && myForm.foobar.hasVisited && myForm.foobar.$error.required">This field is required.</span>
        </li>
        <li>
            <label for="bar">Date Input</label>
            <input id="bar" name="bar" type="date" ng-model="bar" required />
            <span class="error-message" ng-show="!myForm.bar.hasFocus && myForm.bar.hasVisited && myForm.bar.$error.required">This field is required.</span>
            <span class="error-message" ng-show="!myForm.bar.hasFocus && myForm.bar.hasVisited && myForm.bar.$error.date">Please enter a valid date.</span>
        </li>
        <li>
            <label for="barthirty">Datetime Input</label>
            <input id="barthirty" name="barthirty" type="datetime" ng-model="barthirty" required />
            <span class="error-message" ng-show="!myForm.barthirty.hasFocus && myForm.barthirty.hasVisited && myForm.barthirty.$error.required">This field is required.</span>
            <span class="error-message" ng-show="!myForm.barthirty.hasFocus && myForm.barthirty.hasVisited && myForm.barthirty.$error.datetime">Please enter a valid date and time.</span>
        </li>
        <li>
            <label for="baz">Phone Input</label>
            <input id="baz" name="baz" type="tel" ng-model="baz" required />
            <span class="error-message" ng-show="!myForm.baz.hasFocus && myForm.baz.hasVisited && myForm.baz.$error.phone">Not a valid phone...

CSS

html,body{height:100%;}
body,form{padding:1em;}
input,input.ng-invalid.has-visited.has-focus,form{border:1px solid #8d8d8d;}
input,button{border-radius:3px;padding:.25em;}
body{background: #528cc2; /* Old browsers */
background: -moz-linear-gradient(top,  #6dbbff 0%, #528cc2 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#6dbbff), color-stop(100%,#528cc2)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top,  #6dbbff 0%,#528cc2 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top,  #6dbbff 0%,#528cc2 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top,  #6dbbff 0%,#528cc2 100%); /* IE10+ */
background: linear-gradient(to bottom,  #6dbbff 0%,#528cc2 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6dbbff', endColorstr='#528cc2',GradientType=0 ); /* IE6-9 */
font-family:sans-serif;}
ul,li{list-style:none;}
form{background: #f7f7f7; /* Old browsers */
background: -moz-linear-gradient(top,  #f7f7f7 0%, #e5e5e5 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f7f7f7), color-stop(100%,#e5e5e5)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top,  #f7f7f7 0%,#e5e5e5 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top,  #f7f7f7 0%,#e5e5e5 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top,  #f7f7f7 0%,#e5e5e5 100%); /* IE10+ */
background: linear-gradient(to bottom,  #f7f7f7 0%,#e5e5e5 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f7f7f7', endColorstr='#e5e5e5',GradientType=0 ); /* IE6-9 */
border:1px solid #8d8d8d;border-radius:6px;box-shadow:0 3px 5px rgba(0,0,0,.3);min-width:400px;margin:auto;width:50%;}
form li{margin-bottom:.5em;}
label{color:#8d8d8d;display:block;line-height:1.5;}
:focus{outline:0;}
input{background:rgba(255,255,255,.5);}
input:focus{background:#FFF;}
input.ng-invalid.has-visited{border:1px solid...

JavaScript

var app = angular.module("myApp",[]);

function Fiddle($scope){}

app.directive('input', function() {
    return {
        restrict: 'E',
        require: '?ngModel',
        link: function(scope, elm, attr, ctrl) {
            if (!ctrl) {
                return;
            }
            
            elm.bind('focus', function () {
                elm.addClass('has-focus');

                scope.$apply(function () {
                    ctrl.hasFocus = true;
                });
            });

            elm.bind('blur', function () {
                elm.removeClass('has-focus');
                elm.addClass('has-visited');

                scope.$apply(function () {
                    ctrl.hasFocus = false;
                    ctrl.hasVisited = true;
                });
            });
           
            if (attr.type == 'text' && attr.ngPattern === '/[0-9]/') {
                elm.bind('keyup',function (){
                    var text = this.value;
                    console.log(text);
                  this.value = text.replace(/[a-zA-Z]/g,'');
                });
            }  
        }
    };
});