Sam Graber
Sam Graber

Reputation: 43

Radio button two-way binding issue with ng-model

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

Answers (3)

Simon Robb
Simon Robb

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

Srinivas Paila
Srinivas Paila

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

Sebastian Piu
Sebastian Piu

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

Related Questions