1

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/

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

3 Comments

@SebastienPiu is correct, the underlying problem is that the model in the inherited parent scope is being obscured by the child scope after being set from the child scope the first time.
That solution works well, but the idea behind using an ng-click event to trigger the radio buttons is so I can use it on a div style as a table row. It seems kind of hacky to use a label in the same way. Any ideas?
@SamGraber I've taken Sebastien's idea below and applied it to your code at jsfiddle.net/vscvxg40/10. Now, although ng-repeat creates a child scope, the inputs reference the parent scope's selectedItem as its ng-model. Since both the div and the input now reference the same model, there isn't the conflict you were seeing before.
2

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>

Comments

2

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];
    }

1 Comment

This doesn't answer the question. Clicking the input isn't the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.