Embedded forms aren't attached to $scope #8403

Closed
metric152 opened this Issue Jul 29, 2014 · 3 comments

Projects

None yet

2 participants

@metric152

When a form is inside a ng-directive include it's not attached to the $scope object.

I go into detail about it here
http://blog.152.org/2014/07/angular-form-element-not-attaching-to.html

@caitp
Contributor
caitp commented Jul 30, 2014

So, the issue you're describing is really just a misunderstanding about the way scopes in Angular work. It's a bit of a tricky system and admittedly takes some getting used to, but this is working as expected.

ng-controller will create a new scope, as will ng-include whenever it adds a template to the DOM.

So what you end up with is a scope hierarchy like this:

  002 - rootScope
         003 - ngController
                004 - ngInclude

The included form directive adds createUser to the ngInclude scope (called 004 in the chart above, but the IDs in a real application won't necessarily match). You can't get at this via scope003.createUser, because it's lower in the scope hierarchy, you'd have to grab the child scope and get it that way (not recommended).

There are work arounds for this, for instance:

<div ng-controller="controllerName" ng-init="forms = {}; model = {}">
    <div ng-include=" 'path-to-the-template' "></div>
</div>

<!—- Inside path-to-the-template -—>
<form name="forms.createUser">
    <input name="name" ng-model="model.name" />
    <input name="email" ng-model="model.email" />
</form>

This will put the included form in scope003.forms.createUser, and will put the name and email inputs in scope003.model.name and scope003.model.email, respectively. Note, you don't necessarily have identifiers for scope003 declared, this is just indicating that it's in the controller's scope.

Here's an example: http://jsfiddle.net/g8DkL/

This might seem inconvenient, but it's really what you want to do anyways, so that you avoid confusion when new scopes are created that you aren't aware of.

So I don't think we're going to call this a bug, but it is clearly one of those hurdles that you need to jump over while learning the framework, and it is understandably frustrating =)

@caitp caitp closed this Jul 30, 2014
@caitp
Contributor
caitp commented Jul 30, 2014

The reasons why this works this way make sense if you understand prototypical inheritance in javascript (child scopes prototypically inherit from their parent scopes, so scope004.proto === scope003, and scope003.proto === scope002, etc), so if it's unclear from this explanation and example, I suggest reading up on resources regarding that, including https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain

@metric152

Once you said the include will have its own scope my problem made complete sense. I didn't realize that was the case. Thank you so much for the help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment