StackOverflow_24227903: angular-form-validation-but-not-using-inputs

Illustration of answer to http://stackoverflow.com/questions/24227903/angular-form-validation-but-not-using-inputs.

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular-messages.min.js"></script>
<div ng-controller="myCtrl">
    <form name="myForm" ng-submit="sendMessage()" novalidate>
        <div>
            Email:
            <input type="text" name="rcpEmail" ng-model="recipient.email"
                   placeholder="Send email to..." required-any="msgType" />
            <div ng-messages="myForm.rcpEmail.$error" ng-if="myForm.$submitted">
                <div class="error" ng-message="requiredAny">At least one recipient method must be chosen</div>
            </div>
            <br />
            Modile:
            <input type="text" name="rcpMobile" ng-model="recipient.mobile"
                   placeholder="Send SMS to..." required-any="msgType" />
            <div ng-messages="myForm.rcpMobile.$error" ng-if="myForm.$submitted">
                <div class="error" ng-message="requiredAny">At least one recipient method must be chosen</div>
            </div>
            <br />
            Address:
            <input type="text" name="rcpAddress" ng-model="recipient.address"
                   placeholder="Send card to..." required-any="msgType" />
            <div ng-messages="myForm.rcpAddress.$error" ng-if="myForm.$submitted">
                <div class="error" ng-message="requiredAny">At least one recipient method must be chosen</div>
            </div>
        </div>
        <hr />
        <button type="submit">Send message</button>
        <br/>
    </form>
</div>

JavaScript

var app = angular.module('myApp', ['ngMessages']);
app.controller('myCtrl', function ($scope) {
    $scope.sendMessage = function () {
        $scope.myForm.$submitted = true;
        
        if ($scope.myForm.$valid) {
			alert('Message sent !');
        }
    };
});

app.directive('requiredAny', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function postLink(scope, elem, attrs, ctrl) {
            // If there is no 'ngModel' or no groupName has been specified,
            // then there is nothing we can do
            if (!ctrl || !attrs.requiredAny) { return };
            
            // If this is the first time we've used this directive in this scope,
            // create a section for it's data. If you need / want to make use of
            // an isolate scope you'll need to make 'var groups' scoped to the directive;
            // but then you may want to look in to clearing out group entries yourself
            if (!scope.__requiredAnyGroups) {
                scope.__requiredAnyGroups = {}
            }
            var groups = scope.__requiredAnyGroups;
            
            // Create a bucket for this group if one does not yet exist
            if (!groups[attrs.requiredAny]) {
                groups[attrs.requiredAny] = {};
            }
            var group = groups[attrs.requiredAny];
            
            // Create the entry for this control
			group[attrs.ngModel] = {
                ctrl: ctrl,
                hasValue: false
            };
            
            ctrl.$validators.requiredAny = function(view, value) {
                var thisCtrl = group[attrs.ngModel],
                    ctrlValue = (typeof value !== 'undefined') && value,
                    oneHasValue = false;
                
				thisCtrl.hasValue = ctrlValue;

                // First determine if any field in the group has a value
                for (var prop in group) {
                    if...