Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
feat(button): allow uncheckable radio button
Browse files Browse the repository at this point in the history
Acts as a hybrid checkbox/radio-button, selecting exclusively among the button set, but also allowing the selected item to be unselected, leaving the button set without a selected item.

Closes #1760
  • Loading branch information
duncanbeevers authored and bekos committed Apr 9, 2014
1 parent f48e433 commit 82df4fb
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 6 deletions.
6 changes: 4 additions & 2 deletions src/buttons/buttons.js
Expand Up @@ -24,9 +24,11 @@ angular.module('ui.bootstrap.buttons', [])

//ui->model
element.bind(buttonsCtrl.toggleEvent, function () {
if (!element.hasClass(buttonsCtrl.activeClass)) {
var isActive = element.hasClass(buttonsCtrl.activeClass);

if (!isActive || angular.isDefined(attrs.uncheckable)) {

This comment has been minimized.

Copy link
@ferjimriv

ferjimriv Apr 29, 2015

Hi! I found an error in bntRadio directive. It's need to change for this line:

if (!isActive || !angular.isDefined(attrs.uncheckable)) {

This allow the radio to be uncheckable.

scope.$apply(function () {
ngModelCtrl.$setViewValue(scope.$eval(attrs.btnRadio));
ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio));
ngModelCtrl.$render();
});
}
Expand Down
9 changes: 7 additions & 2 deletions src/buttons/docs/demo.html
Expand Up @@ -11,11 +11,16 @@ <h4>Checkbox</h4>
<label class="btn btn-primary" ng-model="checkModel.middle" btn-checkbox>Middle</label>
<label class="btn btn-primary" ng-model="checkModel.right" btn-checkbox>Right</label>
</div>
<h4>Radio</h4>
<pre>{{radioModel}}</pre>
<h4>Radio &amp; Uncheckable Radio</h4>
<pre>{{radioModel || 'null'}}</pre>
<div class="btn-group">
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Left'">Left</label>
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Middle'">Middle</label>
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Right'">Right</label>
</div>
<div class="btn-group">
<label class="btn btn-success" ng-model="radioModel" btn-radio="'Left'" uncheckable>Left</label>
<label class="btn btn-success" ng-model="radioModel" btn-radio="'Middle'" uncheckable>Middle</label>
<label class="btn btn-success" ng-model="radioModel" btn-radio="'Right'" uncheckable>Right</label>
</div>
</div>
3 changes: 1 addition & 2 deletions src/buttons/docs/readme.md
@@ -1,2 +1 @@
There are 2 directives that can make a group of buttons to behave like a set of checkboxes or radio buttons.

There are two directives that can make a group of buttons behave like a set of checkboxes, radio buttons, or a hybrid where radio buttons can be unchecked.
48 changes: 48 additions & 0 deletions src/buttons/test/buttons.spec.js
Expand Up @@ -136,5 +136,53 @@ describe('buttons', function () {
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).toHaveClass('active');
});

describe('uncheckable', function () {
//model -> UI
it('should set active class based on model', function () {
var btns = compileButtons('<button ng-model="model" btn-radio="1" uncheckable>click1</button><button ng-model="model" btn-radio="2" uncheckable>click2</button>', $scope);
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');

$scope.model = 2;
$scope.$digest();
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).toHaveClass('active');
});

//UI->model
it('should unset active class based on model', function () {
var btns = compileButtons('<button ng-model="model" btn-radio="1" uncheckable>click1</button><button ng-model="model" btn-radio="2" uncheckable>click2</button>', $scope);
expect($scope.model).toBeUndefined();

btns.eq(0).click();
expect($scope.model).toEqual(1);
expect(btns.eq(0)).toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');

btns.eq(0).click();
expect($scope.model).toEqual(undefined);
expect(btns.eq(1)).not.toHaveClass('active');
expect(btns.eq(0)).not.toHaveClass('active');
});

it('should watch btn-radio values and update state', function () {
$scope.values = ['value1', 'value2'];

var btns = compileButtons('<button ng-model="model" btn-radio="values[0]" uncheckable>click1</button><button ng-model="model" btn-radio="values[1]" uncheckable>click2</button>', $scope);
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');

$scope.model = 'value2';
$scope.$digest();
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).toHaveClass('active');

$scope.model = undefined;
$scope.$digest();
expect(btns.eq(0)).not.toHaveClass('active');
expect(btns.eq(1)).not.toHaveClass('active');
});
});
});
});

0 comments on commit 82df4fb

Please sign in to comment.