AngularJS: Make ng-model available outside of ng-repeat

Problem

In my AngularJS app, I am looping through an array object and send the value to a radio input as value. The overall idea is that the user selects a radio box and the value with be back part of $routeParams. Unfortunately, the variable {{ modelSelected }} does not seemed to be available outside of the ng-repeat. Why? The first never shows the variable {{ modelSelected }}.

Does AngularJS creates a ScopeChild within the ng-repeat?

Link to my jsfiddle example

<html ng-app>
    <body ng-init="models = [{name:'Sam'},{name:'Harry'},{name:'Sally'}]">
        <h3> Selected {{ modelSelected }} shown outside paragraph</h3>

        <div ng-repeat="model in models">
            <p>{{ model.name }} -
                <input ng-model="modelSelected" type="radio" name="patient" value="{{ model.name }}" required>
            </p>
             <h3> Selected {{ modelSelected }} shown inside paragraph</h3>

        </div>
    </body>
</html>
Problem courtesy of: neurix

Solution

When dealing with primitives or using bindings generally try to prefer using a . in the model property that is being bound. So that when a child scope is created prototypical inheritance will carry down the properties (which are reference types) down to the children. (using $parent almost always is considered as a hack). In your case the property modelSelected is a primitive (even if it is present on the parent scope) and ng-repeat creates a child scope which does not finds this property (since inheritance does not carry it down even if it were present) and creates a new property on its scope, so the changes made to that are not seen to the outer scope.

Initialize a property on the scope as an object, selection={} in your scope (in your example it would be the outerscope). And bind the model as ng-model="selection.modelSelected

Ex:-

<body ng-init="models = [{name:'Sam'},{name:'Harry'},{name:'Sally'}]; selection={}">
        <h3> Selected {{ selection.modelSelected }} shown outside paragraph</h3>

        <div ng-repeat="model in models">
            <p>{{ model.name }} -
                <input ng-model="selection.modelSelected" type="radio" name="patient" value="{{ model.name }}" required>
            </p>
             <h3> Selected {{ selection.modelSelected }} shown inside paragraph</h3>

        </div>
 </body>

Demo

Read: Understanding Scopes

Solution courtesy of: PSL

Discussion

Yes. It does create a new scope that inherits the parent scope. Use $parent.modelSelected to access the parent scope's variable.

<body ng-init="models = [{name:'Sam'},{name:'Harry'},{name:'Sally'}]">
     <h3> Selected {{ modelSelected }} shown outside paragraph</h3>

    <div ng-repeat="model in models">
        <p>{{ model.name }} -
            <input ng-model="$parent.modelSelected" type="radio" name="patient" value="{{ model.name }}" required>
        </p>
         <h3> Selected {{ modelSelected }} shown inside paragraph</h3>

    </div>
</body>
Discussion courtesy of: Rajkumar Madhuram

The {{modelSelected}} would not be available outside the ng-repeat because of how scope works in AngularJS (see https://docs.angularjs.org/guide/scope)

Scopes are arranged in hierarchical structure which mimic the DOM structure of the application

So since the <h3> element you are trying to access the {{modelSelected}} object from is outside the scope of the iterator, the object is not available.

Discussion courtesy of: Spaceman Spiff

This recipe can be found in it's original form on Stack Over Flow.