AngularJS Form Validation with Bootstrap Decorations

Creates a "UserValidation" module with validation directives such as valid-username and valid-password. Sets properties on the scope to turn errors on and off. Turns on errors progressively - ie, one error per field at a time. For the most part, uses angular's built in form validation structure. Does not use built in required directive because I wanted to sequence the errors. (there must be a way to use it and still do this.) Am not pleased with "formAllGood" directive, but "myform.$valid" doesn't work for me, the submit button hides & unhides as the user fills the form out. http://thomporter.com

by Yang Tyler

HTML

<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css">
<div ng-app="myapp">
    <form  name="myform" class="form form-horizontal" ng-controller="myappCtrl">
    <legend>Angular User Validation with Bootstrap Decorations</legend>
    <div class="control-group" ng-class="{error:!myform.myfile.$valid}">
        <label for="inputUsername" class="control-label">Username:</label>
        <div class="controls">
            <input type="file" id="inputUsername" name="myfile" ng-model="myInputFile" valid-file />
            <div class="help-inline">

                <span ng-show="myform.myfile.$error.invalidSize">File size must less than 1000kb.</span>
            </div>
            <div>{{myfile}}</div>
        </div>
    </div>
    
    <div class="form-actions" ng-show="formAllGood()">
        <input type="submit" class="btn btn-primary" value="Submit" />
    </div>
    </form></div>

JavaScript

var app = angular.module('myapp', ['FormValidation']);

myappCtrl = function($scope) {
    $scope.formAllGood = function () {
        return ($scope.usernameGood && $scope.passwordGood && $scope.passwordCGood)
    }
        
}

angular.module('FormValidation', []).directive('validFile', function () {
    return {
        require: 'ngModel',
        link: function (scope, elm, attrs, ngModel) {
            var maxSize = 100;
            var invalidSize = true;
            ngModel.$render = function () {
                // when you setValidity 'invalidSize' to false
                // then you 'form.myfile.$error.invalidSize' will be true.
                ngModel.$setValidity('invalidSize', invalidSize);
            };
            elm.bind('change', function(evt){
                console.log(evt);
                var files = evt.target.files; // You can handle multifile here but need input file set multiple attribute
                var file = files[0];
                console.log(file); // You can see all these attribute here.
                console.log(file.size);
                if(file.size > maxSize){
                    invalidSize = false;
                }else{
                    invalidSize = true;
                }
                scope.$apply(ngModel.$render);
            });
            
/*            
            ngModel.$parsers.unshift(function (viewValue) {
                // Any way to read the results of a "required" angular validator here?
                var isBlank = viewValue === ''
                var invalidChars = !isBlank && !/^[A-z0-9]+$/.test(viewValue)
                var invalidLen = !isBlank && !invalidChars && (viewValue.length < 5 || viewValue.length > 20)
                ngModel.$setValidity('isBlank', !isBlank)
                ngModel.$setValidity('invalidChars', !invalidChars)
                ngModel.$setValidity('invalidLen', !invalidLen)
                scope.usernameGood = !isBlank && !invalidChars && !invalidLen

          ...