Martijn
Martijn

Reputation: 24789

Binding with radio's not working in Angular

Using ng-repeat I display some radio's in the edit form:

<label style="float: left;margin-right: 3px;" data-ng-repeat="gender in genders" data-ng-hide="$first">
    <input type="radio" name="gender"  value="{{gender.Id}}" data-ng-model="customerFormData.customer.Gender.Id" />{{gender.Description}}
</label>

As you can see, I've applied the 'dot practice'. The edit form is a pop-up over my detail form. In my detail form I have this:

<tr>
    <td>Gender:</td>
    <td>{{ customer.Gender.Description }} </td>
</tr>

All my bindings in the edit form are working, but I can't get the gender binding to work. I think it has something to do with scope inheriting by the use of ng-repeat.

I've also tried to use $parent, but the outcome remains the same:

<label style="float: left;margin-right: 3px;" data-ng-repeat="gender in genders" data-ng-hide="$first">
    <input type="radio" name="gender"  value="{{gender.Id}}" data-ng-model="$parent.customerFormData.customer.Gender.Id" />{{gender.Description}}
</label>

Setting the initial value works. When a female is set, the female radio is selected and when it is a male, the male radio is selected.

A second problem is (and I think it has to do with the binding), is that when Male is selected, I have to click twice on female to get female selected.

Edit: I've created a Fiddle to illustrate my issue.

Upvotes: 1

Views: 10284

Answers (3)

Narretz
Narretz

Reputation: 4993

One solution is to use ng-value(which evaluates its content as an expression) and set it to the whole gender object, and set ng-model to the Gender object on your FormData. This way, when you change the input, the gender object is set to FormData.Gender and you have access to both Id and Descr.

<label ng-repeat="gender in genders">    
  <input type="radio" name="gender" ng-value="gender" ng-model="customer.FormData.Gender">
  {{gender.Descr}}
</label>   

http://jsfiddle.net/ADukg/3194/

If you just want the Id in the model, you can use: (value evaluates its content as a string)

<label ng-repeat="gender in genders">
  <input type="radio" name="gender" value="{{gender.Id}}" ng-model="customer.FormData.Gender.Id">
  {{gender.Descr}}
</label>

And in the controller:

$scope.customer.FormData.Gender = {Id : $scope.genders[1].Id};

http://jsfiddle.net/ADukg/3195/

Strangely enough, it doesn't work when you set value and model to Id, but initially bind a whole gender object to the gender model. Weird!

Upvotes: 8

callmekatootie
callmekatootie

Reputation: 11228

The problem lies with the binding on the radio buttons. You are binding on the customer.FormData.Gender.id model - note it is the id property that you bind to and not the Gender property.

Thus, when you select the radio button for Male, only the ID on the gender is changed - not the Descr field. This explains clearly the behaviour. When you select different radio buttons, notice how only the ID gets updated and not the Desc.

To change the Descr field as well, you will be wise to have a dedicated model for the radio buttons and then respond to changes to this model.

This is demonstrated in this fiddle.

Upvotes: 1

DanEEStar
DanEEStar

Reputation: 6280

I can't explain it 100% accurately. But you have too many nested objects in your scope!

Look at this example (fiddle: http://jsfiddle.net/ADukg/3193/)

<div ng-controller="MyCtrl">
    <label ng-repeat="gender in genders">
        <input type="radio" name="gender" value="{{ gender.Id }}" ng-model="$parent.selectedGenderId">{{gender.Descr}}
    </label>
</div>

function MyCtrl($scope) {
    $scope.genders = [{Id: 1, Descr:'Male'}, {Id:2, Descr:'Female'}];
    $scope.selectedGenderId = $scope.genders[1].Id;

    $scope.$watch('selectedGenderId', function(newValue, oldValue) {
        console.log("selectedGenderId=" + newValue);
        // TODO: set it into FormData?
    });
}

If you set the "selectedGenderId" directly it will also be set correctly.

I think the selection problem has nothing to do with the binding directly but with the scope and nesting of scopes via the many objects.

Take also look at this explanation: http://jimhoskins.com/2012/12/14/nested-scopes-in-angularjs.html

Upvotes: 2

Related Questions