AngularJS Radio Groups

Groups of radio buttons that update true/false model values in AngularJS.

by ChrisP

HTML

<div ng-app="app" ng-controller="Main">
    <radio-group group-name="Values of Radio Buttons">
        <radio ng-model="values.v1" id="hello">Hello</radio>
        <radio ng-model="values.v2" id="world">World</radio>
    </radio-group>
    <h5>Values in the Main Controller</h5>
    <p>hello: {{values.v1}}<br/>world: {{values.v2}}</p>
    <p ng-show="values.v1">Hello Selected</p>
    <p ng-show="values.v2">World Selected</p>
</div>

JavaScript

var app = angular.module('app', []);

app.controller('Main', function ($scope) {
    $scope.values = {v1: true, v2: false};
});

app.directive('radioGroup', function () {
    return {restrict: 'EA',
            replace: true,
            transclude: true,
            scope: {name: '@groupName'},
            template: '<div><h5>{{name}}</h5><div ng-transclude></div>'+
            '<h5>Values in Radio Group Controller</h5><div ng-repeat="r in radios">{{r.id}}: {{r.ngModel}}</div>'+
            '</div>',
            controller: function ($scope, $element) {
                var radios = [];
                $scope.radios = radios;
                // return the name of this group
                this.getName = function () { return $element.attr('group-name'); }
                // add a radio item to the group
                this.addRadioItem = function (r) {
                    radios.push(r);
                }
                // cycle through and update the model when any single radio changes state
                this.select = function (chosen) {
                    angular.forEach(radios, function (r) {
                        if (chosen != r) {
                            r.ngModel = false;
                        }
                    });
                $scope.$apply();
                };
            }};
});
app.directive('radio', function () {
    return {restrict: 'EA',
            replace: true,
            transclude: true,
            require: '^radioGroup',
            scope: {id: '@',
                    ngModel: '='},
            template: '<label><input id="{{id}}" name="{{name}}" type="radio" ng-checked="ngModel"/>'+
            '<span ng-transclude></span> ({{ngModel}})</label>',
            link: function (scope, element, attrs, radioGroupController) {
                scope.name = radioGroupController.getName();
                // include this item in the radio group
                radioGroupController.addRadioItem(scope);
                // update...