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: "joDoe@domain.com",
isPrimary: 'false',
isTechnical: true,
isSales: false,
isBilling: true,
isEmergency: true
}, {
name: "Jane Doe",
email: "jaDoe@domain.com",
isPrimary: 'true',
isTechnical: false,
isSales: false,
isBilling: true,
isEmergency: true
}, {
name: "Bill Murray",
email: "bMurray@domain.com",
isPrimary: 'false',
isTechnical: false,
isSales: true,
isBilling: false,
isEmergency: false
}, {
name: "Someone Dude",
email: "someone@domain.com",
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: "joDoe@domain.com",
isPrimary: false,
isTechnical: true,
isSales: false,
isBilling: true,
isEmergency: true
}, {
name: "Jane Doe",
email: "jaDoe@domain.com",
isPrimary: true,
isTechnical: false,
isSales: false,
isBilling: true,
isEmergency: true
}, {
name: "Bill Murray",
email: "bMurray@domain.com",
isPrimary: false,
isTechnical: false,
isSales: true,
isBilling: false,
isEmergency: false
}, {
name: "Someone Dude",
email: "someone@domain.com",
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/