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

feat(button): add new button directive #54

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
33 changes: 33 additions & 0 deletions src/button/button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
angular.module('ui.bootstrap.button', [])

.directive('button', ['$parse', function($parse) {
return {
restrict: 'E',
compile:function (tElement, tAttrs, transclude) {
tElement.addClass('btn');
return function (scope, element, attrs) {
if (attrs.toggle){

var exprGetter = $parse(attrs.toggle);
var exprSetter = exprGetter.assign;

//watch model changes
scope.$watch(attrs.toggle, function(newVal){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could just watch exprGetter, since angular will be $parsing it internally anyway if you provide an expression.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I got you here...

if (newVal) {
element.addClass('active');
} else {
element.removeClass('active');
}
});

//watch click events
element.bind('click', function(){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just thought of this, but we should be keeping click events out of our code. On mobile, they are bad (need a tap event). We should keep the events in template. Although here I'm not sure how to make the event mobile configurable... A template for this directive would be too much.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeh, adding event in a directive is bad... although I thought that it will react to tap events as well, need to test.

What worries me more is is the fact that the class name (active) is hard-coded here.
I like the idea of this directive less and less :-)

Maybe we really should just do a generic class-toggle and be done with it? WDYT?

scope.$apply(function(){
exprSetter(scope, !exprGetter(scope));
});
});
}
};
}
};
}]);
14 changes: 14 additions & 0 deletions src/button/docs/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div ng-controller="ButtonCtrl">

<h4>Single toggle</h4>
<button toggle="single.selected" class="">Click me!</button>
<pre>{{single | json}}</pre>

<h4>Checkbox</h4>
<div class="btn-group" data-toggle="buttons-checkbox">
<button toggle="group.left" class="btn-primary">Left</button>
<button toggle="group.middle" class="btn-primary">Middle</button>
<button toggle="group.right" class="btn-primary">Right</button>
</div>
<pre>{{group | json}}</pre>
</div>
11 changes: 11 additions & 0 deletions src/button/docs/demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var ButtonCtrl = function ($scope) {
$scope.single = {
selected: true
};

$scope.group = {
left:false,
middle:true,
right:false
};
};
3 changes: 3 additions & 0 deletions src/button/docs/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The `button` directive will style all the buttons with the `btn` class.

Additionally it adds support for the `toggle='expression'` attribute. This attribute, if pointed to an assignable expression, will turn a button into a fancy check-box.
49 changes: 49 additions & 0 deletions src/button/test/button.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
describe('button', function () {

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

describe('initial state', function () {
it('should render button without active class if no toggle attribute present selected', function () {
var elm = $compile('<button>Click me</button>')($rootScope);
$rootScope.$digest();

expect(elm).toHaveClass('btn');
expect(elm).not.toHaveClass('active');
});

it('should render button without active class if the toggle attribute evaluates to false', function () {
var elm = $compile('<button toggle="selected">Click me</button>')($rootScope);
$rootScope.$apply('selected = false');

expect(elm).toHaveClass('btn');
expect(elm).not.toHaveClass('active');
});

it('should render button with active class if the toggle attribute evaluates to true', function () {
var elm = $compile('<button toggle="selected">Click me</button>')($rootScope);
$rootScope.$apply('selected = true');

expect(elm).toHaveClass('btn');
expect(elm).toHaveClass('active');
});
});

describe('click event', function () {

it('should toggle class on click if the toggle attribute is present', function () {
var elm = $compile('<button toggle="selected">Click me</button>')($rootScope);
$rootScope.$apply('selected = true');

expect($rootScope.selected).toEqual(true);
elm.click();
expect($rootScope.selected).toEqual(false);
elm.click();
expect($rootScope.selected).toEqual(true);
});
});
});