Michael Moussa
Michael Moussa

Reputation: 4297

How can I check an ng-included form's validity from the parent scope?

I have a subform that is shared among multiple views in my app. In one view, this subform is displayed alone with a back/continue button at the bottom that leads the user to the next subform. In another view, the subform is displayed on the same page as other subforms (basically one long form).

Since the html of the subform is 100% identical in both views, I separated it into a partial and am using ng-include to render it. In the view that displays only the subform with the back/continue buttons, I render the back/continue buttons within the parent's HTML.

Visually, everything works fine, and I'm able to access all of the data entered in the form (user.email, user.password, user.etc...).

The problem is that I'm enabling/disabling the "continue" button based on whether or not the user has completed the form correctly, and this does not work in the "subform-only" variation because the parent scope doesn't seem to be able to access the form's status. If I stick the buttons in the partial, it works, but I don't want to do that because the buttons don't belong there in every instance that this partial is being used.

JSFiddle Example

Notice in my example that the submit button within the red border is disabled until something is typed in the box and the "Form Invalid?" value updates, while the button within the blue border is always enabled and the "Form Invalid?" value is blank.

How can I access the value of myForm.$invalid from the parent scope?

Upvotes: 28

Views: 12696

Answers (2)

Scott Driscoll
Scott Driscoll

Reputation: 2929

The child scope created when you use ng-include is hiding the form functions from the parent.

In addition to using a directive, you can also add an object in the parent, but it's important to set the name of the form to an object with a property like so:

<form name="myFormHolder.myForm">

and in the parent controller

$scope.myFormHolder = {};

then the following should work:

$scope.myFormHolder.myForm.$pristine

This way when the form is evaluated, myForm.$valid will get set on the parent. I believe I asked this same question: Why form undefined inside ng-include when checking $pristine or $setDirty()?

Upvotes: 25

joakimbl
joakimbl

Reputation: 18081

If it's a sub-form you can just move the form-tag from the sub-form and into the main-form: updated JSFiddle

You could also nest your forms using the ngForm-directive:

In angular forms can be nested. This means that the outer form is valid when all of the child forms are valid as well. However browsers do not allow nesting of elements, for this reason angular provides ngForm alias which behaves identical to but allows form nesting.

The result is a bit messy imo. I'd rather create a 'myForm'-directive with a new scope to avoid using $parent - something like:

myApp.directive('myForm',function(){
    return{ 
        restrict:'E',
        scope:{model:'='},
        templateUrl:'/form.html',
        replace:true
    }
});

- see this JSFiddle example

Upvotes: 15

Related Questions