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

Commit b155051

Browse files
feat(buttons): add checkbox and radio buttons
Closes #53
1 parent 9a867a2 commit b155051

File tree

5 files changed

+200
-0
lines changed

5 files changed

+200
-0
lines changed

src/buttons/buttons.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
angular.module('ui.bootstrap.buttons', [])
2+
3+
.constant('buttonConfig', {
4+
activeClass:'active'
5+
})
6+
7+
.directive('btnRadio', ['buttonConfig', function (buttonConfig) {
8+
var activeClass = buttonConfig.activeClass || 'active';
9+
10+
return {
11+
12+
require:'ngModel',
13+
link:function (scope, element, attrs, ngModelCtrl) {
14+
15+
var value = scope.$eval(attrs.btnRadio);
16+
17+
//model -> UI
18+
scope.$watch(function () {
19+
return ngModelCtrl.$modelValue;
20+
}, function (modelValue) {
21+
if (angular.equals(modelValue, value)){
22+
element.addClass(activeClass);
23+
} else {
24+
element.removeClass(activeClass);
25+
}
26+
});
27+
28+
//ui->model
29+
element.bind('click', function () {
30+
if (!element.hasClass(activeClass)) {
31+
scope.$apply(function () {
32+
ngModelCtrl.$setViewValue(value);
33+
});
34+
}
35+
});
36+
}
37+
};
38+
}])
39+
40+
.directive('btnCheckbox', ['buttonConfig', function (buttonConfig) {
41+
42+
var activeClass = buttonConfig.activeClass || 'active';
43+
44+
return {
45+
require:'ngModel',
46+
link:function (scope, element, attrs, ngModelCtrl) {
47+
48+
var trueValue = scope.$eval(attrs.btnCheckboxTrue);
49+
var falseValue = scope.$eval(attrs.btnCheckboxFalse);
50+
51+
trueValue = angular.isDefined(trueValue) ? trueValue : true;
52+
falseValue = angular.isDefined(falseValue) ? falseValue : false;
53+
54+
//model -> UI
55+
scope.$watch(function () {
56+
return ngModelCtrl.$modelValue;
57+
}, function (modelValue) {
58+
if (angular.equals(modelValue, trueValue)) {
59+
element.addClass(activeClass);
60+
} else {
61+
element.removeClass(activeClass);
62+
}
63+
});
64+
65+
//ui->model
66+
element.bind('click', function () {
67+
scope.$apply(function () {
68+
ngModelCtrl.$setViewValue(element.hasClass(activeClass) ? falseValue : trueValue);
69+
});
70+
});
71+
}
72+
};
73+
}]);

src/buttons/docs/demo.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<div ng-controller="ButtonsCtrl">
2+
<h4>Single toggle</h4>
3+
<pre>{{singleModel}}</pre>
4+
<button type="button" class="btn btn-primary" ng-model="singleModel" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
5+
Single Toggle
6+
</button>
7+
<h4>Checkbox</h4>
8+
<pre>{{checkModel}}</pre>
9+
<div class="btn-group" data-toggle="buttons-checkbox">
10+
<button type="button" class="btn btn-primary" ng-model="checkModel.left" btn-checkbox>Left</button>
11+
<button type="button" class="btn btn-primary" ng-model="checkModel.middle" btn-checkbox>Middle</button>
12+
<button type="button" class="btn btn-primary" ng-model="checkModel.right" btn-checkbox>Right</button>
13+
</div>
14+
<h4>Radio</h4>
15+
<pre>{{radioModel}}</pre>
16+
<div class="btn-group" data-toggle="buttons-checkbox">
17+
<button type="button" class="btn btn-primary" ng-model="radioModel" btn-radio="'Left'">Left</button>
18+
<button type="button" class="btn btn-primary" ng-model="radioModel" btn-radio="'Middle'">Middle</button>
19+
<button type="button" class="btn btn-primary" ng-model="radioModel" btn-radio="'Right'">Right</button>
20+
</div>
21+
</div>

src/buttons/docs/demo.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var ButtonsCtrl = function ($scope) {
2+
3+
$scope.singleModel = 1;
4+
5+
$scope.radioModel = 'Middle';
6+
7+
$scope.checkModel = {
8+
left: false,
9+
middle: true,
10+
right: false
11+
};
12+
};

src/buttons/docs/readme.md

Whitespace-only changes.

src/buttons/test/buttons.spec.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
describe('buttons', function () {
2+
3+
var $scope, $compile;
4+
5+
beforeEach(module('ui.bootstrap.buttons'));
6+
beforeEach(inject(function (_$rootScope_, _$compile_) {
7+
$scope = _$rootScope_;
8+
$compile = _$compile_;
9+
}));
10+
11+
describe('checkbox', function () {
12+
13+
var compileButton = function (markup, scope) {
14+
var el = $compile(markup)(scope);
15+
scope.$digest();
16+
return el;
17+
};
18+
19+
//model -> UI
20+
it('should work correctly with default model values', function () {
21+
$scope.model = false;
22+
var btn = compileButton('<button ng-model="model" btn-checkbox>click</button>', $scope);
23+
expect(btn).not.toHaveClass('active');
24+
25+
$scope.model = true;
26+
$scope.$digest();
27+
expect(btn).toHaveClass('active');
28+
});
29+
30+
it('should bind custom model values', function () {
31+
$scope.model = 1;
32+
var btn = compileButton('<button ng-model="model" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">click</button>', $scope);
33+
expect(btn).toHaveClass('active');
34+
35+
$scope.model = 0;
36+
$scope.$digest();
37+
expect(btn).not.toHaveClass('active');
38+
});
39+
40+
//UI-> model
41+
it('should toggle default model values on click', function () {
42+
$scope.model = false;
43+
var btn = compileButton('<button ng-model="model" btn-checkbox>click</button>', $scope);
44+
45+
btn.click();
46+
expect($scope.model).toEqual(true);
47+
btn.click();
48+
expect($scope.model).toEqual(false);
49+
});
50+
51+
it('should toggle custom model values on click', function () {
52+
$scope.model = 0;
53+
var btn = compileButton('<button ng-model="model" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">click</button>', $scope);
54+
55+
btn.click();
56+
expect($scope.model).toEqual(1);
57+
btn.click();
58+
expect($scope.model).toEqual(0);
59+
});
60+
});
61+
62+
describe('radio', function () {
63+
64+
var compileButtons = function (markup, scope) {
65+
var el = $compile('<div>'+markup+'</div>')(scope);
66+
scope.$digest();
67+
return el.find('button');
68+
};
69+
70+
//model -> UI
71+
it('should work correctly set active class based on model', function () {
72+
var btns = compileButtons('<button ng-model="model" btn-radio="1">click1</button><button ng-model="model" btn-radio="2">click2</button>', $scope);
73+
expect(btns.eq(0)).not.toHaveClass('active');
74+
expect(btns.eq(1)).not.toHaveClass('active');
75+
76+
$scope.model = 2;
77+
$scope.$digest();
78+
expect(btns.eq(0)).not.toHaveClass('active');
79+
expect(btns.eq(1)).toHaveClass('active');
80+
});
81+
82+
//UI->model
83+
it('should work correctly set active class based on model', function () {
84+
var btns = compileButtons('<button ng-model="model" btn-radio="1">click1</button><button ng-model="model" btn-radio="2">click2</button>', $scope);
85+
expect($scope.model).toBeUndefined();
86+
87+
btns.eq(0).click();
88+
expect($scope.model).toEqual(1);
89+
90+
btns.eq(1).click();
91+
expect($scope.model).toEqual(2);
92+
});
93+
});
94+
});

0 commit comments

Comments
 (0)