1

I wrote an AngularJS directive with a form. The form has a required text field as well as two other forms. Each of them child forms has another required text field.

The difference between the 2 child forms is how I create them:

  1. The first child form is compiled and appended to a div.
  2. The second child form is directly included in the template of the directive.

If the second child form is invalid, the whole outter form becomes invalid. This is what I expected. However, if the first child form (the one I compiled manually) becomes invalid, it has no influence on the outter parent form. Why?

enter image description here

var app = angular.module('plunker', []);

app.component('generator', {
    template: "<ng-form name=\"outterForm\">" + 
                  "<input name=\"out\" ng-model=\"$ctrl.out\" ng-minlength=\"5\" ng-required=\"true\" type=\"text\" />" + 
                  "<div id=\"component-container\"></div>" +
                  "<my-text></my-text>" +
                  "<div>Valid outterForm: {{outterForm.$valid}}</div>" +
              "</ng-form>",
    controller: function($compile, $scope, $document) {
        var componentContainer = $document.find('#component-container');
        var template = "<my-text></my-text>";
        var childScope = $scope.$new();
        var result = componentContainer.append(template);
        $compile(result)(childScope);
    }
});

app.component('myText', {
    template: "<ng-form name=\"innerForm\"><input name=\"name\" ng-model=\"$ctrl.name\" ng-minlength=\"5\" ng-required=\"true\" type=\"text\" />Valid innerForm: {{innerForm.$valid}}</ng-form>"
});

Here's the running Plunker:

https://plnkr.co/edit/YfBRY4xPvKgqDtWXFMUi

4
  • whats the point of nesting form? stackoverflow.com/questions/379610/can-you-nest-html-forms Commented Jan 19, 2017 at 13:22
  • You cannot next HTML forms, but you can nest ng-forms. This is useful if you use components. A component might implement a form. If you re-use this component in another form, you will have two nested forms. I thinks this is absolutely valid. Commented Jan 19, 2017 at 13:37
  • may be forms should have different names then? idk, too lazy to test it Commented Jan 19, 2017 at 13:58
  • Good point, but unfortunately this changes nothing. Commented Jan 19, 2017 at 14:10

1 Answer 1

1

That's because $$parentForm of sub-form's formController hasn't been set after you compile that sub-form. And I don't know why, it needs more deep knowledge I suppose.

I tried to $compile()() in different compilation stages (preLink, postLink) and had same result. However I almost achieve the goal with two methods:

  • First is to assign $$parentForm directly like this childScope.innerForm.$$parentForm = scope.outterForm;. Here is my plunker example (notice I changed components to directives, cause they are more flexible).
  • Second is to recompile parent form (but this makes useless manual sub-form compilation). Here is the second plunker example.

But! In both methods there is one huge problem - setting sub-forms names and models dynamically (it should be so, cause you want to use one directive on multiple sub-forms).

In first method there is no errors, but one bug: when you change model of the second sub-form it changes model of the first one (it stops when you once adjust model of the first sub-form).

In the second method everything seems to work fine, but at backstage there are a lot of errors occurs each time you change model.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks a lot for your explanation! I also discovered one more thing: If you put a normal HTML form around everything, this form behaves as expected and only becomes valid if all child forms are valid. Here's the Plunker if your're interested: plnkr.co/edit/YfBRY4xPvKgqDtWXFMUi
If you change your new outer form to ng-form it will work too =) I think the thing is to have child directives to be compiled before parents in order to work correctly. All sub-forms have been already compiled before the outer one starts to.
ngForm is a dynamic form part and needs a parent <form /> tag, isn't a form itself. Nest ngForms will work too, due to the nature of this directive, which looks for a reference to belong to, but the lower reference, being a ngForm too, will need a parent reference too. So, the relation between them only work because they can belong to a parent. The correct way to use is setup a form, nest its ngForm parts conditionally and even manually compiled ones will work. But, just wondering: is it just an experiment? Why do you need to compile something like that manually?
@MateusDuartePoncedeLeon I try to build an application which generates a big form based on an external configuration which comes as JSON from the backend. That's the background of my question :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.