Reputation: 43
I'm having an issue with radio button two-way binding using ng-model and ng-value. I have three radio buttons, created within an ng-repeat. They all of the same ng-model, $scope.selectedItem
, and each button's ng-value is the current item in the ng-repeat. This seems to work fine. The issue comes when I want to set the selected item in the controller. Here I have an ng-click event select()
that sets the selectedItem to the item passed in.
function MyCtrl($scope) {
$scope.list = [{
id: 1
}, {
id: 2
}, {
id: 3
}];
$scope.select = function (item) {
$scope.selectedItem = item;
}
}
<div ng-repeat="item in list" class="interactive" ng-click="select(item)">
<input type="radio" name="itemSelector" ng-model="selectedItem" ng-value="item" />
{{item.id}}
</div>
This works as long as I only select the item using the ng-click event. If I click #1 using the radio button directly, then select #2 using the ng-click event, then fire the ng-click event for #1, the second radio button gets unchecked, but the first one doesn't become selected. When I observe in the debugger, I can tell that the value of selectedItem is getting set successfully, it's just the radio button that isn't updating.
Is there something wrong with the way that I'm using the radio button bindings? Is there a way to fix this?
JSFiddle: https://jsfiddle.net/SamGraber/vscvxg40/4/
Upvotes: 1
Views: 3753
Reputation: 1698
Definitely a strange behaviour. I'm not sure what's causing your issue but see a workaround here https://jsfiddle.net/vscvxg40/9/.
Note this is recommended HTML practice anyway - the wrapper div
is now a label
, which triggers the radio selection when it is clicked.
Upvotes: 2
Reputation: 827
Here is a fiddle that solves your problem http://jsfiddle.net/paila/7ax5tspc/
The problem is with the scope of the selectedItem variable on controller scope.
When the radio buttons are generated using ng-repeat, and the selectedItem is changed a new variable is created on each child scope and the selectedItem on controller scope is never modified.
Using an object to hold the value of selected item will resolve this. When you do so, the child scopes can override objects properties and they reflect back to parent controller scope.
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.list = [{
id: 1
}, {
id: 2
}, {
id: 3
}];
$scope.selected = {};
$scope.selected.Item = $scope.list[0];
}
Upvotes: 2
Reputation: 8008
ng-repeat
creates a child scope, so you just need to bind ng-model to the $parent
scope. No need for ng-click
at all as ng-model already does bi-directional binding for you. see fiddle here http://jsfiddle.net/d1570gfk/1/
<div ng-repeat="item in list" class="interactive">
<input type="radio" name="itemSelector" ng-model="$parent.selectedItem" ng-value="item" /{{item.id}}
</div>
Upvotes: 2