ng-change event only fires once for each radio button when created with ng-repeat

angularjs, angularjs-directive

Solution

Use an object instead of a primitive value:

app.controller('mainController', ['$scope', function (scope) {
  scope.environment = { value: '' };
}]);

Remove `ng-change` and `$watch`. `ng-model` will be enough (unless I'm misunderstanding the use case).

Demo: http://jsfiddle.net/GLAQ8/

Very good post on prototypal inheritance can be found here.

Problem

I have created an AngularJS directive with radio buttons to control which environment my page will query against and added it to my page. I am using a two-way binding to map a local scope variable called `environment` to an app variable with the same name. It seems to work well when I create the radio buttons explicitly in the template (in my actual code I'm using `templateUrl` instead, but still have the same problem). ``` <div> <label><input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(1)" value="1" />Testing</label> <label><input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(2)" value="2" />Production</label> </div> ``` I can select each choice as many times as I want, and the value bubbles all the way up to the app's scope variable. I wanted to change the creation of the radio buttons to use `ng-repeat` on an array of choice objects. It creates the options, and it captures the `ngChange` event, but only once for each choice. ``` <label ng-repeat="choice in choices"> <input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(choice)" value="{{ choice.id }}" />{{ choice.name }} </label> ``` Here is the working version fiddle and the relevant parts of my directive code: ``` template: '<div>' + '<label><input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(1)" value="1" />Testing</label>' + '<label><input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(2)" value="2" />Production</label>' + '<div>Directive environment: {{ environment }}</div>' + '</div>', link: function(scope, element, attributes) { scope.changeEnvironment = function(choiceID) { console.log('SELECTED environment ' + choiceID); scope.environment = choiceID; console.log('directive environment = ' + scope.environment); }; } ``` And here is the version that only works once: ``` template: '<div><label ng-repeat="choice in choices">' + '<input type="radio" name="env" ng-model="environment" ng-change="changeEnvironment(choice)" value="{{ choice.id }}" />{{ choice.name }}' + '</label>' + '<div>Directive environment: {{ environment }}</div>' + '</div>', link: function(scope, element, attributes) { scope.choices = [ { id: 1, name: "Testing" }, { id: 2, name: "Production" } ]; scope.changeEnvironment = function(choice) { console.log('SELECTED environment ' + choice.id); scope.environment = choice.id; console.log('directive environment = ' + scope.environment); }; } ``` I'm brand-new to AngularJS, so it's entirely possible I'm making a very basic mistake. Can anyone point me in the right direction? UPDATE As per callmekatootie's suggestion, I changed the event in question from `ng-change` to `ng-click`, and it fires every time. That will do as a work-around for now, but I originally used `ng-change` because I didn't think `ng-click` would apply to changes caused by clicking on the text label rather than the input itself, but in fact it does. Still don't get why `ng-change` only fires once, though.

Original source

Related problems