Reputation: 33962
I feel like i'm just missing something here, but I can't see what. I can't seem to get the value of the radio button to behave in the same way as the checkboxes. What am I doing wrong?
Here's a demo: http://jsfiddle.net/vwJ6a/2/
Here's an idea of what my HTML looks like
<tr ng-repeat="contact in ContactsList">
<td>{{contact.name}}</td>
<td>{{contact.email}}</td>
<td ng-class="{'success':contact.isPrimary}">
<input type="radio" name="radio-primary" ng-model="contact.isPrimary" />
</td>
<td ng-class="{'success':contact.isTechnical}">
<input type="checkbox" ng-model="contact.isTechnical" />
</td>
</tr>
And here's my Controller
function MyCtrl($scope) {
$scope.ContactsList = [{
name: "John Doe",
email: "[email protected]",
isPrimary: false,
isTechnical: true
}, {
name: "Jane Doe",
email: "[email protected]",
isPrimary: true,
isTechnical: false
}, {
name: "Bill Murray",
email: "[email protected]",
isPrimary: false,
isTechnical: false
}, {
name: "Someone Dude",
email: "[email protected]",
isPrimary: false,
isTechnical: false
}];
}
Upvotes: 2
Views: 22914
Reputation: 1845
Nice question! I was stuck on a similar problem and implemented kind of a work around. First of all, I don't think that you want the radio buttons to behave in the same way like the checkboxes. Checkboxes allow multiple values while radios don't. Probably that was clear, I just want to state it in order to prevent a misunderstanding.
The AngularJS documentation gives some explanation on the usage of radio buttons. https://docs.angularjs.org/api/ng/input/input[radio] The explanation doesn't take a real "dynamic" environment in account. As you can see, the colours are prefixed in the example. I assume, that you want your table to be completely dynamic, without prefixing anything.
The first thing I did are the following changes in the HTML:
<form name="myForm" ng-controller="MyCtrl">
<h4>Primary: {{GetPrimaryContact().email}}</h4>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Primary</th>
<th>Technical</th>
<th>Sales</th>
<th>Billing</th>
<th>Emergency</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="contact in ContactsList">
<td>{{contact.name}}</td>
<td>{{contact.email}}</td>
<td ng-class="{'success':contact.isPrimary == 'true'}">
<input type="radio" name="radio-primary" ng-model="contact.isPrimary" value="true" ng-change="update($index)" />
</td>
<td ng-class="{'success':contact.isTechnical}">
<input type="checkbox" ng-model="contact.isTechnical" />
</td>
<td ng-class="{'success':contact.isSales}">
<input type="checkbox" ng-model="contact.isSales" />
</td>
<td ng-class="{'success':contact.isBilling}">
<input type="checkbox" ng-model="contact.isBilling" />
</td>
<td ng-class="{'success':contact.isEmergency}">
<input type="checkbox" ng-model="contact.isEmergency" />
</td>
</tr>
</tbody>
</table>
</form>
The success
class-check compares isPrimary
to string 'true'. I am not able to use real boolean values when working with comparing on radio buttons.
Additionally, there is a value="true"
now which is required for the comparison (It checks the line, where isPrimary is in fact true
). Last thing is a new method in the ng-change
part. We need this, because we need to tell the controller that the other values are false, when one value changes to true. This is why we also give the $index
of the ng-repeat
iteration to the method, because the value which is currently changed to true
doesn't need to be false
again.
Here is the new Controller:
function MyCtrl($scope) {
$scope.ContactsList = [{
name: "John Doe",
email: "[email protected]",
isPrimary: 'false',
isTechnical: true,
isSales: false,
isBilling: true,
isEmergency: true
}, {
name: "Jane Doe",
email: "[email protected]",
isPrimary: 'true',
isTechnical: false,
isSales: false,
isBilling: true,
isEmergency: true
}, {
name: "Bill Murray",
email: "[email protected]",
isPrimary: 'false',
isTechnical: false,
isSales: true,
isBilling: false,
isEmergency: false
}, {
name: "Someone Dude",
email: "[email protected]",
isPrimary: 'false',
isTechnical: false,
isSales: false,
isBilling: false,
isEmergency: true
}];
$scope.GetPrimaryContact = function () {
return _.findWhere($scope.ContactsList, {
isPrimary: 'true'
});
};
$scope.update = function(index) {
for (var i=0;i<$scope.ContactsList.length;i++) {
if (index != i) {
$scope.ContactsList[i].isPrimary = 'false';
}
}
};
}
The controller includes the changes, that isPrimary
uses Strings instead of Booleans and the new update()
method. Here is a link to a working demo in jsfiddle: http://jsfiddle.net/vwJ6a/20/
Update:
Chris and me found obviously a way, to use real boolean values for the radio button in ng-repeat.
In order to use it, ng-value="true"
has to be used instead of value="true"
. value
does not seem to work, I got the idea here: AngularJS - Binding radio buttons to models with boolean values
The HTML part will look like this:
<form name="myForm" ng-controller="MyCtrl">
<h4>Primary: {{GetPrimaryContact().email}}</h4>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Primary</th>
<th>Technical</th>
<th>Sales</th>
<th>Billing</th>
<th>Emergency</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="contact in ContactsList">
<td>{{contact.name}}</td>
<td>{{contact.email}}</td>
<td ng-class="{'success':contact.isPrimary}">
<input type="radio" name="radio-primary" ng-value="true" ng-model="contact.isPrimary" ng-checked="contact.isPrimary" ng-change="UpdatePrimary(contact)" />
</td>
<td ng-class="{'success':contact.isTechnical}">
<input type="checkbox" ng-model="contact.isTechnical" />
</td>
<td ng-class="{'success':contact.isSales}">
<input type="checkbox" ng-model="contact.isSales" />
</td>
<td ng-class="{'success':contact.isBilling}">
<input type="checkbox" ng-model="contact.isBilling" />
</td>
<td ng-class="{'success':contact.isEmergency}">
<input type="checkbox" ng-model="contact.isEmergency" />
</td>
</tr>
</tbody>
</table>
</form>
and the controller like this:
function MyCtrl($scope) {
$scope.ContactsList = [{
name: "John Doe",
email: "[email protected]",
isPrimary: false,
isTechnical: true,
isSales: false,
isBilling: true,
isEmergency: true
}, {
name: "Jane Doe",
email: "[email protected]",
isPrimary: true,
isTechnical: false,
isSales: false,
isBilling: true,
isEmergency: true
}, {
name: "Bill Murray",
email: "[email protected]",
isPrimary: false,
isTechnical: false,
isSales: true,
isBilling: false,
isEmergency: false
}, {
name: "Someone Dude",
email: "[email protected]",
isPrimary: false,
isTechnical: false,
isSales: false,
isBilling: false,
isEmergency: true
}];
$scope.GetPrimaryContact = function () {
return _.findWhere($scope.ContactsList, {
isPrimary: true
});
};
$scope.UpdatePrimary = function(contact) {
_.each($scope.ContactsList, function(x) {
x.isPrimary = (x.email === contact.email);
});
};
}
Here is a demo in jsfiddle: http://jsfiddle.net/vwJ6a/24/
Upvotes: 5
Reputation: 43947
The main difference is checkboxes allow multiples selections while radio buttons dont.
That's why radio buttons should share the same model. In your case, the ngModel
s point to different objects.
This is how I would get around it:
<td ng-class="{'success':primaryContact.email == contact.email}">
<input type="radio" name="radio-primary" ng-model="primaryContact.email"
ng-value="contact.email"/>
</td>
$scope.primaryContact = {
email:"[email protected]"
};
Upvotes: 5
Reputation: 3779
I believe if you add value="1" to your radio input line, you'll get the results you're looking for.
<input type="radio" value="1" name="radio-primary" ng-model="contact.isPrimary" />
Upvotes: 0