<!DOCTYPE html>
<html>

<head>
  <link data-require="bootstrap-css@3.0.3" data-semver="3.0.3" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" />
  <script data-require="angular.js@1.2.11" data-semver="1.2.11" src="http://code.angularjs.org/1.2.11/angular.js"></script>
  <script data-require="ui-bootstrap@0.10.0" data-semver="0.10.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-app="app" ng-controller="MainCtrl">
  <h1>Disable children</h1>

  <label>
    <input type="checkbox" ng-model="disableAll" /> Tapa kaikki
  </label>

  <div ng-form="Form">
    <div disable-children="disableAll">
    <ul>
      <li>
        <label>
          <input type="radio" ng-model="selection" ng-value="'first'" name="selection" ng-required="'true'" />First selection
        </label>
        <div disable-children="selection !== 'first'">
          Text here:
          <input type="text" ng-model="ekaText" name="ekaText" ng-pattern="/^[a-zA-Z]+$/" ng-required="selection === 'first'"
            disable-validation="selection !== 'first'">
        </div>
      </li>
      <li>
        <label>
          <input type="radio" ng-model="selection" ng-value="'second'" name="selection" ng-required="'true'" />Second selection
        </label>
        <div disable-children="selection !== 'second'">
          Numbers:
          <input type="text" ng-model="tokaText" name="tokaText" ng-pattern="/^[0-9]+$/" ng-required="'true'"
            disable-validation="selection !== 'second'">
          
          <select name="tokaSel" ng-model="tokaSel" ng-required="'true'" disable-validation="selection !== 'second'">
            <option value="">Not selected</option>
            <option value="foo">Selected</option>
            <option value="bar">Selected 2</option>
          </select>
        </div>
      </li>
    </ul>

    <h2>
        Valid?
        <span ng-show="Form.$valid" style="color:green">Yippii!</span>
        <span ng-show="Form.$invalid" style="color:red">Not :(</span>
      </h2>
      
      <pre>
        Selection: {{selection}}
        Eka: {{ekaText}}
        Toka: {{tokaText}}
        Toka: {{tokaSel}}
        
Formi:
  {{Form | json}}
        
Errorit:
  {{Form.$error | json}}
        
        Eka errors:  {{Form.ekaText.$error}}
        Toka errors: {{Form.tokaText.$error}}
        Tokasel err: {{Form.tokaSel.$error}}
      </pre>
      </div>
  </div>
</body>

</html>
// Code goes here

angular.module("app", [])

.controller('MainCtrl', function($scope) {

  $scope.selection = 'first';

})

/*
.directive('disableValidation', function() {
  return {
    restrict: 'A',
    require: ['ngModel','^form'],
    priority: 10,
    controller: function() {
      this.foo = function() {};
    },
    link: function(scope, element, attrs, ctrls) {
      var ngModel = ctrls[0];
      var form = ctrls[1];
      
      scope.$watch(attrs.disableValidation, function(v) {
        var ctrl = ngModel;
        
        if (v) {
          attrs.$set('disabled', 'disabled');
          form.$removeControl(ctrl);
        } else {
          attrs.$set('disabled', null);
          form.$addControl(ctrl);
          angular.forEach(ctrl.$error, function(validity, validationToken) {
            form.$setValidity(validationToken, !validity, ctrl);
          });
        }
      });
    }
  };
})
*/


.directive('disableChildren', function() {
  return {
    restrict: 'A',
    link: function(scope,element,attrs) {
      var findChildren = function() {
        var children = [];
        angular.forEach(element.find("input"), function(elem) {
          children.push(elem);
        });
        angular.forEach(element.find("select"), function(elem) {
          children.push(elem);
        });
        return children;
      };
      
      /**
       * Key-value pair of models and their form controllers 
       */
      var childModelCtrls = [];
      
      var saveChildren = function() {
        childModelCtrls = [];
        angular.forEach(findChildren(), function(e) {
          var elem = angular.element(e);
          var ngModel = elem.controller('ngModel');
          var form = elem.inheritedData('$formController');
          childModelCtrls.push({element: elem, ngModel: ngModel, ngForm: form});
        });  
      };
      
      
      scope.$watch(attrs.disableChildren, function(val) {
        if (val) {
          saveChildren();
          console.log("Saved children", childModelCtrls);
          angular.forEach(childModelCtrls, function(child) {
            child.ngForm.$removeControl(child.ngModel);
            child.ngModel._$setValidity = child.ngModel.$setValidity;
            child.ngModel.$setValidity = function() {};
          });
        } else {
          angular.forEach(childModelCtrls, function(child) {
            var ngModel = child.ngModel;
            var ngForm = child.ngForm;
            ngModel.$setValidity = ngModel._$setValidity;
            ngForm.$addControl(ngModel);
            angular.forEach(ngModel.$error, function(validity, validationToken) {
              ngForm.$setValidity(validationToken, !validity, ngModel);
            });
          })
        }
      });
    }
  }
})
/* Styles go here */

input.ng-dirty.ng-invalid {
  border: 1px solid red;  
}