-
Notifications
You must be signed in to change notification settings - Fork 6.7k
feat(button): add new button directive #54
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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){ | ||
if (newVal) { | ||
element.addClass('active'); | ||
} else { | ||
element.removeClass('active'); | ||
} | ||
}); | ||
|
||
//watch click events | ||
element.bind('click', function(){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 ( Maybe we really should just do a generic |
||
scope.$apply(function(){ | ||
exprSetter(scope, !exprGetter(scope)); | ||
}); | ||
}); | ||
} | ||
}; | ||
} | ||
}; | ||
}]); |
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> |
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 | ||
}; | ||
}; |
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. |
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); | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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...