Toggling AngularJS Radio Buttons

by Faisal Pathan

HTML

<h1>
Anguler Radio button event individual
</h1>
<p>
    This fiddle demonstrates how we can leverage AngularJS 
    and its model to create radio buttons that toggle. 
    There are two pairs of radio buttons to show how it 
    can work across multiple groups and with a default 
    setting.
</p>
<p>
    Tapping once selects; tapping again deselects.
</p>
<div ng-app ng-controller="Example">
    
    <!-- First pair of radio buttons -->
    <input type="radio" id="radio1" ng-model="test1"
           ng-click="toggle($event)" 
           ng-keydown="toggle($event)"
           value="one" tabindex="1" />
    <label for="radio1">One</label>
    <input type="radio" id="radio2" ng-model="test1"
           ng-click="toggle($event)"
           ng-keydown="toggle($event)"
           value="two" tabindex="2"/>
    <label for="radio2">Two</label>
    <p>{{test1}}</p>

    <hr />

    <!-- Second pair of radio buttons -->
    <input type="radio" id="radio3" ng-model="test2" ng-click="toggle($event)" value="one" checked="checked" />
    <label for="radio3">One</label>
    <input type="radio" id="radio4" ng-model="test2" ng-click="toggle($event)" value="two" />
    <label for="radio4">Two</label>
    <p>{{test2}}</p>

</div>

CSS

label {
    -webkit-user-select: none;
    -moz-user-select: none;    
    -ms-user-select: none;
    user-select: none;
}

JavaScript

function Example($scope) {
    
    /*
     * When an element is clicked, the model has not yet
     * been updated, so we check the value of the model 
     * to the value of the clicked element.  If they are 
     * identical, then the user is clicking the "current"
     * (selected) option and we can toggle it by setting 
     * the model to null.
     */
    $scope.toggle = function(event) {
        var keyboardEvent = event.type == 'keydown'
        var spaceOrEnterKey = keyboardEvent &&
                            (event.which == 13 ||
                             event.which == 32)
        var elem = event.target
        var modelKey = angular.element(elem).attr('ng-model')
        if (elem.value == $scope[modelKey]
           && (!keyboardEvent || spaceOrEnterKey)) {
            $scope[modelKey] = null
        } else {
            if (spaceOrEnterKey)
                $scope[modelKey] = elem.value
        }
        if (spaceOrEnterKey)
            event.preventDefault()
    }

    // Demonstrate radio button with default selection
    $scope.test2 = 'two'
}