Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

How can I skip validation of nested forms with AngularJS? I have to make an outer form valid even when its child form is invalid.

In the example below outer form should be valid (fOuter.$valid must be true). By default, it is not. Is there an option?

Code (jsFiddle):

<div ng-app ng-controller="Ctrl">  
    <ng-form name="fOuter">  
        <h3>Outer form (valid={{fOuter.$valid}})</h3>  
        <input type="text" name="txtOuter" ng-model="outer" placeholder="(required)" required />  
        <ng-form name="fInner">  
            <h3>Inner form (valid={{fInner.$valid}})</h3>  
            <input type="text" name="txtInner" ng-model="inner" placeholder="(required)" required />  
        </ng-form>  
    </ng-form>  
</div>
share|improve this question
    
so Outer invalid only if both inners are invalid, right? –  Maxim Shoustin Oct 12 '13 at 11:20
    
I want to make outer form valid if its own text field is valid (and not pay attention to invalid fields in the inner form). –  Antelle Oct 12 '13 at 11:22
add comment

3 Answers

up vote 0 down vote accepted

In Angular forms can be nested. This means that the outer form is valid when all of the child forms are valid as well.

So there is no way to make outer form to be valid automatically (through $valid key) when one of inner invalid.

Try to use error.required

   <h3>Outer form (valid={{!fOuter.txtOuter.$error.required}})</h3>

Demo Fiddle

From Angular ngForm docs:

The other way should be to use controller, like:

<h3>Outer form (valid={{isOuterFormValid}})</h3>

controller

$scope.isOuterFormValid = true;

// here, add listener on each input and change flag `isOuterFormValid`
... 
share|improve this answer
    
No, this does not solve the problem: $pristine will be set to false when the user change any field. –  Antelle Oct 12 '13 at 11:27
    
yes but i used or pristine or invalid. You always get true –  Maxim Shoustin Oct 12 '13 at 11:27
    
in this case, outer will be $valid when txtOuter is empty. –  Antelle Oct 12 '13 at 11:29
    
See my edit now, true on any text, false on empty –  Maxim Shoustin Oct 12 '13 at 11:39
    
It's true but only for one field; I have plenty of; so, to check the outer form state, I must enumerate all fields in it manually; I want angularjs to do that automatically (but exclude fields that are in inner form). –  Antelle Oct 12 '13 at 11:48
show 6 more comments

I am a newbie to Angular however, please check whether the below approach helps.

<div ng-app ng-controller="Ctrl"> <ng-form name="fOuter"> <h3>Outer form (valid={{fOuter.$valid}})</h3> <ng-form name="fInner1"> <h3>Inner form 1 (valid={{fInner1.$valid}})</h3> <input type="text" name="txtInner1" ng-model="outer" placeholder="(required)" required /> </ng-form> <ng-form name="fInner2"> <h3>Inner form 2 (valid={{fInner2.$valid}})</h3> <input type="text" name="txtInner2" ng-model="inner" placeholder="(required)" required /> </ng-form> </ng-form> </div>

share|improve this answer
add comment

I faced the same problem. Inside a larger form I needed to have a subform with several controls that shouldn't touch the state of the parent form.

Here's my solution: I wrote a directive "null-form" that removes the subform from the parent form and that does not send any state changes its parent.

angular.module('nullForm',[]).directive('nullForm', [function () {
  return {
    restrict: 'A',
    require: '?form',
    link: function link(scope, element, iAttrs, formController) {

      if (! formController) {
        return;
      }

      // Remove this form from parent controller
      var parentFormController = element.parent().controller('form');
      parentFormController.$removeControl(formController);

      // Replace form controller with a "null-controller"
      var nullFormCtrl = {
        $addControl: angular.noop,
        $removeControl: angular.noop,
        $setValidity: angular.noop,
        $setDirty: angular.noop,
        $setPristine: angular.noop
      };

      angular.extend(formController, nullFormCtrl);
    }
  };
}]);

You can then use it like this:

<form name="parent">
  <input type="text" ng-model="outside"/>
  <form name="subform" null-form>
    <input type="text" ng-model="inside"/>
  </form>
</form>

Any change or negative validation of "inside" won't take an effect on "parent".

There's one downside, however, due to this solution: subform will not have any state either nor will its CSS classes like ng-invalid etc. work. To accomplish this you would need to re-implement this functionality from the original form-controller.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.