Binding with radio's not working in Angular - angularjs

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.

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!

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

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.

Related

How can i show a control depending upon value in a list using AngularJS?

I have a list retuned from MVC controller to angular controller as follows:
result.data.mylist = (<Test1, true>,<Test2, false>,<Test3, true>)
I have 3 controls*textboxes) that always sit on a form , TextBox1, TextBox2, TextBox3.
I want to only show the textbox where the value is true.
So in the above , since Test1 = true (TextBox1 is visible) and TextBox3 is visible since Test3 is true.
I can do it if it was a simple binding but how do i even start this in AngularJS ?
Use Angular's built-in *ngIf directive.
For example,
<input type="checkbox" *ngIf="result.data.mylist[0]">
<input type="checkbox" *ngIf="result.data.mylist[1]">
<input type="checkbox" *ngIf="result.data.mylist[2]">
Assuming that result.data.mylist is an array containing boolean values.
Alternatively, you could disable them using,
<input type="checkbox" [disabled]="result.data.mylist[0]">
<input type="checkbox" [disabled]="result.data.mylist[1]">
<input type="checkbox" [disabled]="result.data.mylist[2]">

angularjs radiobutton groups having its own model

I want to create a a 3 radio button groups each having its own unique model using one ng-repeat. How can I achieve this?
<div class="radio" data-ng-repeat="item in selItem.items" >
<label class="control-label">
<input type="radio"
data-ng-value={{item.vm}}
data-ng-model="????"
name="{{selItem.Title}}"/>{{item.dm}}
</label>
</div>
First and foremost, why would you do that? Radio buttons are for a unique selection among a group of options, so having the same model for all radio buttons is the way to go.
However, for setting unique ng-models for each item iteration inside ng-repeat, you have to use object bracket notation, using $index or a property of each iteration itself to name the property of the object model.
<div ng-repeat="item in items">
<input type="text" ng-model="myModel[item.name]" >
</div>
check this fiddle to see it working

Check one checkbox should not select the whole checkbox group

Following is the code I am using to populate the checkbox list.
<label class="checkbox-inline" ng-repeat="item in vm.ItemList track by item .id">
<input type="checkbox" name ="item " ng-value="item .id" ng-model ="vm.selecteditem" />{{item.name}}
</label>
The above code selects all the items in ItemList. I need to select only one item from itemList. How do I do that?
https://vitalets.github.io/checklist-model/
This link worked for me!
1) set checklist-model instead of ng-model
2) set checklist-value instead of ng-value
You're attaching the same externalized variable vm.selectedItem to every checkbox. Because of this, when you check one it changes that variable to true in turn selecting all of the checkboxes because they are bound to the same variable which is now true.
My advice to you would be to attach a selected property to each item in ItemList. Then have that attached to the ng-model as shown below.
<label class="checkbox-inline" ng-repeat="item in vm.ItemList track by item .id">
<input type="checkbox" name ="item " ng-value="item .id" ng-model= "item.selected" />{{item.name}}
</label>

How to set checkbox selected on the basis of model value

I have a checkbox and the value of this checkbox is fixed as 'A'. I want the checkbox selected if the model value matches with checkbox value attribute.
<div class="form-horizontal">
<label class="col-md-2">
<input type="checkbox" id="Animals" name="Animals" ng-model="ModelData.Animals" value="A" /> Animal(s)
</label>
</div>
But using the above code, checkbox selection is not working automatically. How can I achieve this?
Please, try to use: ng-checked="ModelData.Animals == 'A'"
More information about ng-checked:
http://docs.angularjs.org/api/ng.directive:ngChecked
You need to use the ng-checked directive to check it with an expression.
Here is a working example: fiddle

How to bind 2 models to one input field in Angular?

Is there anyway that I can bind two model values to one input field?
Suppose I have input field which I want to be the value of two variables in the scope something like:
<input type="text" model="sn_number; id" >
You cannot, but there are some workarounds.
1. Use ngChange to update the other model
<input type="text"
ng-model="sn_number"
ng-change="id=sn_number"/>
2. You could watch a model, and when in changes, update another
$scope.$watch('sn_number', function(v){
$scope.id = v;
});
You would need to watch also for changes in id if you want to keep them in sync.
Example here
You can bind fields immediately, not only in ng-change, and actually it isn't data binding, its only angular expression
<label>Name</label>
<input type="text" ng-model="name" value="{{name}}"/>
<label>Key</label>
<input type="text" ng-model="key" value="{{key=name}}" />
It would make no sense to bind an input to two variables in the model. Binding works both ways, so if the model is updated, the field is updated and vice-versa. If you were to bind to two variables, what would be the single source of truth?
However you can use ng-change to call a method on the controller which can set two variables when the field changes.
with ng-init
<div ng-controller="ctrl" ng-init="model = { year: '2013', month:'09'}">
or
<div ng-repeat="c in contact" ng-init="likes = { food: 'steak', drink:'coke'}">

Resources