Directive for validation messages using config object

Setting the validation message block up as directives.

by vaiism

HTML

<script src="http://code.angularjs.org/angular-1.0.0rc7.min.js"></script>
<p>Directive For Validation Messages</p>
<hr/>
<div ng-app="interfaceSettings" ng-controller="TestDirective" ng-cloak>
    <ul style="font-size:0.9em;">
        <li><b>AngularVersion:</b> {{settings.angularVersion.full}}</li>
        <li><b>ServerType:</b> {{settings.serverType}}</li>
        <li><b>ServerName:</b> {{settings.serverName}}</li>
        <li><b>ServerIP:</b> {{settings.serverIPAddress}}</li>
    </ul>
    <hr/>
    <p><b>Block Created Manually</b></p>
    <div id="validationError" style="display:none;" class="alert_box error" ng-show="settingsForm.$invalid">
        <ul>
            <li ng-show="settingsForm.serverName.$error.required"><b>Required: </b> Server Name</li>
            <li ng-show="settingsForm.serverType.$error.required"><b>Required: </b> Server Type</li>
            <li ng-show="settingsForm.serverType.$error.pattern"><b>Wrong Format: </b> Server Type</li>
            <li ng-show="settingsForm.serverIPAddress.$error.pattern"><b>Wrong Format: </b> Server IP Address</li>
        </ul>
    </div>
    
    <hr/>
    <b>Block created With Directive</b>
    <ei-validation-messages form="settingsForm" config="validationConfig"></ei-validation-messages>

    <hr/>

    <form name="settingsForm">
        <ei-text-field model="settings.serverName" label="Server Name" field-name="serverName" required="true"></ei-text-field>

        <ei-text-field model="settings.serverIPAddress" label="Server IP" field-name="serverIPAddress" pattern="ipv4">(Pattern matters)</ei-text-field>
        
        <ei-text-field model="settings.serverType" label="Server Type" field-name="serverType" pattern="serverTypePattern" required="true">(Must be 'Sun*')</ei-text-field>
        
    </form>

</div>

CSS

body {
    padding: 10px; 
    font-family: sans-serif; 
    font-size: 0.8em;
}
form label {font-weight:bold;margin-right:10px;font-size:0.9em;}
form label:after {content:':';}

// Layout
form .row {width: 90%; display: inline-block;}
form .row:after { content: '.';display: block;clear: both;visibility: hidden;line-height: 0;height: 10px;}


.column {float: left;}
.columnOne {width:25%;}
.columnTwo {width:70%;}


#validationError {
    padding: 0.77em;
}
#validationError:before {
    content: 'The information provided is either invalid or incomplete.';
}
#validationError ul { margin-top: 15px; margin-left: 25px;list-style: disc; }
#validationError ul li { border:solid 1pt #ddd; }
input.ng-invalid, select.ng-invalid, textarea.ng-invalid, input.formElement.ng-invalid {
    border: solid 1pt red;
}
.alert_box.error, #errorExplanation {
    background-color: #FFEFF0;
    border: solid 1pt #DE5462;
}
li {content: '*   ';}

JavaScript

var settingsModule = angular.module('interfaceSettings', []);
/*
 * Order:
 *     > config()
 *       > run()
 *         > controller()
 */
settingsModule.config(function() {});
settingsModule.run(function() {});

// The validations message block.
settingsModule.directive('eiValidationMessages', function() {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            form: 'accessor',
            config: 'accessor'
        },
        template:
'<div id="validationError" style="display:none;" class="alert_box error" ng-show="form().$invalid">' +
'    <ul>' +
'        <li ng-repeat="error in form().$error.required"><b>Required:</b> {{error.$name | validationLabel:config()}}</li>' +
'        <li ng-repeat="error in form().$error.pattern"><b>Wrong Format:</b> {{error.$name | validationLabel:config()}}</li>' +
'        <li ng-repeat="error in form().$error.minlength"><b>Value Too Short:</b> {{error.$name | validationLabel:config()}}</li>' +
'        <li ng-repeat="error in form().$error.maxlength"><b>Value Too Long:</b> {{error.$name | validationLabel:config()}}</li> ' +              
'    </ul>' +
'</div>',
        link: function(scope, element, attrs, controller) {
            scope.localForm = {};         

            // Setup the binding to know when form status changes.
            scope.$watch(function() {return scope.form()}, function(value) {
                scope.localForm = value;
            });
        }
    };
});

// For the text field.
settingsModule.directive('eiTextField', function() {
    return {
        restrict: 'EA',
        replace: true,
        require: '?form',
        transclude: true,
        scope: {
           model: 'accessor',
           label: 'attribute',
           fieldName: 'attribute',
           pattern: 'accessor',
           required: 'evaluate'
        },
        
        // This template for some reason wouldn't work as inline 'textEntryPattern' above
        // says 'has no method 'replace'.
    ...