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

feat(buttons): add checkbox and radio buttons #152

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/buttons/buttons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
angular.module('ui.bootstrap.buttons', [])

.constant('buttonConfig', {
activeClass:'active'
})

.directive('btnRadio', ['buttonConfig', function (buttonConfig) {
var activeClass = buttonConfig.activeClass || 'active';

return {

require:'ngModel',
link:function (scope, element, attrs, ngModelCtrl) {

var value = scope.$eval(attrs.btnRadio);

//model -> UI
scope.$watch(function () {
return ngModelCtrl.$modelValue;
}, function (modelValue) {
if (angular.equals(modelValue, value)){
element.addClass(activeClass);
} else {
element.removeClass(activeClass);
}
});

//ui->model
element.bind('click', function () {
if (!element.hasClass(activeClass)) {
scope.$apply(function () {
ngModelCtrl.$setViewValue(value);
});
}
});
}
};
}])

.directive('btnCheckbox', ['buttonConfig', function (buttonConfig) {

var activeClass = buttonConfig.activeClass || 'active';

return {
require:'ngModel',
link:function (scope, element, attrs, ngModelCtrl) {

var trueValue = scope.$eval(attrs.btnCheckboxTrue);
var falseValue = scope.$eval(attrs.btnCheckboxFalse);

trueValue = angular.isDefined(trueValue) ? trueValue : true;
falseValue = angular.isDefined(falseValue) ? falseValue : false;

//model -> UI
scope.$watch(function () {
return ngModelCtrl.$modelValue;
}, function (modelValue) {
if (angular.equals(modelValue, trueValue)) {
element.addClass(activeClass);
} else {
element.removeClass(activeClass);
}
});

//ui->model
element.bind('click', function () {
scope.$apply(function () {
ngModelCtrl.$setViewValue(element.hasClass(activeClass) ? falseValue : trueValue);
});
});
}
};
}]);
21 changes: 21 additions & 0 deletions src/buttons/docs/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div ng-controller="ButtonsCtrl">
<h4>Single toggle</h4>
<pre>{{singleModel}}</pre>
<button type="button" class="btn btn-primary" ng-model="singleModel" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
Single Toggle
</button>
<h4>Checkbox</h4>
<pre>{{checkModel}}</pre>
<div class="btn-group" data-toggle="buttons-checkbox">
<button type="button" class="btn btn-primary" ng-model="checkModel.left" btn-checkbox>Left</button>
<button type="button" class="btn btn-primary" ng-model="checkModel.middle" btn-checkbox>Middle</button>
<button type="button" class="btn btn-primary" ng-model="checkModel.right" btn-checkbox>Right</button>
</div>
<h4>Radio</h4>
<pre>{{radioModel}}</pre>
<div class="btn-group" data-toggle="buttons-checkbox">
<button type="button" class="btn btn-primary" ng-model="radioModel" btn-radio="'Left'">Left</button>
<button type="button" class="btn btn-primary" ng-model="radioModel" btn-radio="'Middle'">Middle</button>
<button type="button" class="btn btn-primary" ng-model="radioModel" btn-radio="'Right'">Right</button>
</div>
</div>
12 changes: 12 additions & 0 deletions src/buttons/docs/demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var ButtonsCtrl = function ($scope) {

$scope.singleModel = 1;

$scope.radioModel = 'Middle';

$scope.checkModel = {
left: false,
middle: true,
right: false
};
};
Empty file added src/buttons/docs/readme.md
Empty file.
94 changes: 94 additions & 0 deletions src/buttons/test/buttons.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
describe('buttons', function () {

var $scope, $compile;

beforeEach(module('ui.bootstrap.buttons'));
beforeEach(inject(function (_$rootScope_, _$compile_) {
$scope = _$rootScope_;
$compile = _$compile_;
}));

describe('checkbox', function () {

var compileButton = function (markup, scope) {
var el = $compile(markup)(scope);
scope.$digest();
return el;
};

//model -> UI
it('should work correctly with default model values', function () {
$scope.model = false;
var btn = compileButton('<button ng-model="model" btn-checkbox>click</button>', $scope);
expect(btn).not.toHaveClass('active');

$scope.model = true;
$scope.$digest();
expect(btn).toHaveClass('active');
});

it('should bind custom model values', function () {
$scope.model = 1;
var btn = compileButton('<button ng-model="model" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">click</button>', $scope);
expect(btn).toHaveClass('active');

$scope.model = 0;
$scope.$digest();
expect(btn).not.toHaveClass('active');
});

//UI-> model
it('should toggle default model values on click', function () {
$scope.model = false;
var btn = compileButton('<button ng-model="model" btn-checkbox>click</button>', $scope);

btn.click();
expect($scope.model).toEqual(true);
btn.click();
expect($scope.model).toEqual(false);
});

it('should toggle custom model values on click', function () {
$scope.model = 0;
var btn = compileButton('<button ng-model="model" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">click</button>', $scope);

btn.click();
expect($scope.model).toEqual(1);
btn.click();
expect($scope.model).toEqual(0);
});
});

describe('radio', function () {

var compileButtons = function (markup, scope) {
var el = $compile('<div>'+markup+'</div>')(scope);
scope.$digest();
return el.find('button');
};

//model -> UI
it('should work correctly set active class based on model', function () {
var btns = compileButtons('<button ng-model="model" btn-radio="1">click1</button><button ng-model="model" btn-radio="2">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 work correctly set active class based on model', function () {
var btns = compileButtons('<button ng-model="model" btn-radio="1">click1</button><button ng-model="model" btn-radio="2">click2</button>', $scope);
expect($scope.model).toBeUndefined();

btns.eq(0).click();
expect($scope.model).toEqual(1);

btns.eq(1).click();
expect($scope.model).toEqual(2);
});
});
});