Why the inputs are not working right with ng-repea

2019-01-09 19:42发布

问题:

This question already has an answer here:

  • What are the nuances of scope prototypal / prototypical inheritance in AngularJS? 3 answers

Could someone explain to me why I can't get the current selected radio-button in this simple example. I'm trying to generate dynamically the radio-buttons with an ng-repeat directive and get the current radio-button selected using ng-model. Like this:

Template:

<div ng-repeat="kind in movieKinds">
    <input type="radio" name="movies" ng-value="kind" ng-model="kindSelected"> {{kind.name}}<br>
</div>
Selected Movie :{{kindSelected}}

Controller:

mymodule.controller('MainCtrl', [ '$scope',function ($scope) {

    $scope.movieKinds = [
        {'name' : 'Action', 'movies' : ['Action#1', 'Action#2', 'Action#3']},
        {'name' : 'Comedy', 'movies' : ['Comedy#1', 'Comedy#2', 'Comedy#3']},
        {'name' : 'Drama', 'movies' : ['Drama#1', 'Drama#2']},
        {'name' : 'Horror', 'movies' : ['Horror#1']}
    ];

}]);

回答1:

Because ng-repeat does create a new child scope(prototypically inherited) on each iteration when it repeats a template on wherever ng-repeat directive has been placed.

So what happens when ng-repeat creates a new prototypically inherited child scope?

In the child scope it carries all properties in which primitive property initial value taken while creating child scope & object values are taken with their references so update in parent scope value will update in child scope value & vice versa.

Here in your case you had ng-model="kindSelected" variable inside ng-repeat so that scope variable got create inside the ng-repeat scope and doesn't available outside ng-repeat directive.

To fix such a problem you could use object while defining ng-model so that you could follow Dot rule while defining ng-model. That means you could define a object called as $scope.model inside controller & then add kindSelected property so that the value will get updated on selection of checkbox.

Markup

<div ng-repeat="kind in movieKinds">
    <input type="radio" name="movies" ng-value="kind" ng-model="kindSelected"> {{kind.name}}<br>
</div>
Selected Movie :{{model.kindSelected}}

Code

$scope.model = {};

The other way to fix this problem is to use controllerAs syntax which will use alias of controller so the scope hierarchy related problem doesn't happen on HTML. Whichever controller variable you want you could use that alias of the controller.