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

Commit

Permalink
feat(accordion): remove replace: true usage
Browse files Browse the repository at this point in the history
- Remove usage of `replace: true`
- Remove unnecessary `panel-class` feature

BREAKING CHANGE: This removes usage of `replace: true` in the accordion group, which results in a template change where the template no longer needs to contain the panel itself, but its contents. The accordion group will add the `panel` class by default, so the user just needs to add the appropriate classes to the accordion group element. This allows the user to use ng-class as well to fully control the panel related classes, so `panel-class` now is unnecessary

Closes #5985
  • Loading branch information
wesleycho committed Jun 12, 2016
1 parent e2016fd commit 3819bbe
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 100 deletions.
3 changes: 2 additions & 1 deletion src/accordion/accordion.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
return {
require: '^uibAccordion', // We need this directive to be inside an accordion
transclude: true, // It transcludes the contents of the directive into the template
replace: true, // The element containing the directive will be replaced with the template
restrict: 'A',
templateUrl: function(element, attrs) {
return attrs.templateUrl || 'uib/template/accordion/accordion-group.html';
},
Expand All @@ -74,6 +74,7 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
};
},
link: function(scope, element, attrs, accordionCtrl) {
element.addClass('panel');
accordionCtrl.addGroup(scope);

scope.openClass = attrs.openClass || 'panel-open';
Expand Down
52 changes: 25 additions & 27 deletions src/accordion/docs/demo.html
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
<div ng-controller="AccordionDemoCtrl">
<script type="text/ng-template" id="group-template.html">
<div class="panel {{panelClass || 'panel-default'}}">
<div class="panel-heading">
<h4 class="panel-title" style="color:#fa39c3">
<a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading">
<span uib-accordion-header ng-class="{'text-muted': isDisabled}">
{{heading}}
</span>
</a>
</h4>
</div>
<div class="panel-collapse collapse" uib-collapse="!isOpen">
<div class="panel-body" style="text-align: right" ng-transclude></div>
</div>
<div class="panel-heading">
<h4 class="panel-title" style="color:#fa39c3">
<a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading">
<span uib-accordion-header ng-class="{'text-muted': isDisabled}">
{{heading}}
</span>
</a>
</h4>
</div>
<div class="panel-collapse collapse" uib-collapse="!isOpen">
<div class="panel-body" style="text-align: right" ng-transclude></div>
</div>
</script>

Expand All @@ -28,35 +26,35 @@ <h4 class="panel-title" style="color:#fa39c3">
</label>
</div>
<uib-accordion close-others="oneAtATime">
<uib-accordion-group heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
<div uib-accordion-group class="panel-default" heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
This content is straight in the template.
</uib-accordion-group>
<uib-accordion-group heading="{{group.title}}" ng-repeat="group in groups">
</div>
<div uib-accordion-group class="panel-default" heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</uib-accordion-group>
<uib-accordion-group heading="Dynamic Body Content">
</div>
<div uib-accordion-group class="panel-default" heading="Dynamic Body Content">
<p>The body of the uib-accordion group grows to fit the contents</p>
<button type="button" class="btn btn-default btn-sm" ng-click="addItem()">Add Item</button>
<div ng-repeat="item in items">{{item}}</div>
</uib-accordion-group>
<uib-accordion-group heading="Custom template" template-url="group-template.html">
</div>
<div uib-accordion-group class="panel-default" heading="Custom template" template-url="group-template.html">
Hello
</uib-accordion-group>
<uib-accordion-group is-open="status.isCustomHeaderOpen" template-url="group-template.html">
</div>
<div uib-accordion-group class="panel-default" is-open="status.isCustomHeaderOpen" template-url="group-template.html">
<uib-accordion-heading>
Custom template with custom header template <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.isCustomHeaderOpen, 'glyphicon-chevron-right': !status.isCustomHeaderOpen}"></i>
</uib-accordion-heading>
World
</uib-accordion-group>
<uib-accordion-group heading="Delete account" panel-class="panel-danger">
</div>
<div uib-accordion-group class="panel-danger" heading="Delete account">
<p>Please, to delete your account, click the button below</p>
<button class="btn btn-danger">Delete</button>
</uib-accordion-group>
<uib-accordion-group is-open="status.open">
</div>
<div uib-accordion-group class="panel-default" is-open="status.open">
<uib-accordion-heading>
I can have markup, too! <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
</uib-accordion-heading>
This is just some content to illustrate fancy headings.
</uib-accordion-group>
</div>
</uib-accordion>
</div>
5 changes: 0 additions & 5 deletions src/accordion/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ The body of each accordion group is transcluded into the body of the collapsible
_(Default: `false`)_ -
Whether accordion group is open or closed.

* `panel-class`
<i class="glyphicon glyphicon-eye-open"></i>
_(Default: `panel-default`)_ -
Add ability to use Bootstrap's contextual panel classes (panel-primary, panel-success, panel-info, etc...) or your own. This must be a string.

* `template-url`
_(Default: `uib/template/accordion/accordion-group.html`)_ -
Add the ability to override the template used on the component.
Expand Down
81 changes: 23 additions & 58 deletions src/accordion/test/accordion.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,21 +176,21 @@ describe('uib-accordion', function() {

var tpl =
'<uib-accordion>' +
'<uib-accordion-group heading="title 1" template-url="foo/bar.html"></uib-accordion-group>' +
'<div uib-accordion-group heading="title 1" template-url="foo/bar.html"></div>' +
'</uib-accordion>';

element = $compile(tpl)(scope);
scope.$digest();
expect(element.find('[template-url]').html()).toBe('baz');
expect(element.find('[template-url]').html()).toBe('<div>baz</div>');
}));

describe('with static panels', function() {
beforeEach(function() {
spyOn(Math, 'random').and.returnValue(0.1);
var tpl =
'<uib-accordion>' +
'<uib-accordion-group heading="title 1">Content 1</uib-accordion-group>' +
'<uib-accordion-group heading="title 2">Content 2</uib-accordion-group>' +
'<div uib-accordion-group heading="title 1">Content 1</div>' +
'<div uib-accordion-group heading="title 2">Content 2</div>' +
'</uib-accordion>';
element = angular.element(tpl);
$compile(element)(scope);
Expand Down Expand Up @@ -288,8 +288,8 @@ describe('uib-accordion', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<uib-accordion-group heading="title 1" open-class="custom-open-class">Content 1</uib-accordion-group>' +
'<uib-accordion-group heading="title 2" open-class="custom-open-class">Content 2</uib-accordion-group>' +
'<div uib-accordion-group heading="title 1" open-class="custom-open-class">Content 1</div>' +
'<div uib-accordion-group heading="title 2" open-class="custom-open-class">Content 2</div>' +
'</uib-accordion>';
element = angular.element(tpl);
$compile(element)(scope);
Expand Down Expand Up @@ -318,7 +318,7 @@ describe('uib-accordion', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}">{{group.content}}</uib-accordion-group>' +
'<div uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}">{{group.content}}</div>' +
'</uib-accordion>';
element = angular.element(tpl);
model = [
Expand Down Expand Up @@ -363,8 +363,8 @@ describe('uib-accordion', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<uib-accordion-group heading="title 1" is-open="open.first">Content 1</uib-accordion-group>' +
'<uib-accordion-group heading="title 2" is-open="open.second">Content 2</uib-accordion-group>' +
'<div uib-accordion-group heading="title 1" is-open="open.first">Content 1</div>' +
'<div uib-accordion-group heading="title 2" is-open="open.second">Content 2</div>' +
'</uib-accordion>';
element = angular.element(tpl);
scope.open = { first: false, second: true };
Expand Down Expand Up @@ -393,8 +393,8 @@ describe('uib-accordion', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<uib-accordion-group heading="title 1" is-open="open1"><div ng-repeat="item in items">{{item}}</div></uib-accordion-group>' +
'<uib-accordion-group heading="title 2" is-open="open2">Static content</uib-accordion-group>' +
'<div uib-accordion-group heading="title 1" is-open="open1"><div ng-repeat="item in items">{{item}}</div></div>' +
'<div uib-accordion-group heading="title 2" is-open="open2">Static content</div>' +
'</uib-accordion>';
element = angular.element(tpl);
scope.items = ['Item 1', 'Item 2', 'Item 3'];
Expand All @@ -421,7 +421,7 @@ describe('uib-accordion', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}" is-open="group.open">{{group.content}}</uib-accordion-group>' +
'<div uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}" is-open="group.open">{{group.content}}</div>' +
'</uib-accordion>';
element = angular.element(tpl);
scope.groups = [
Expand Down Expand Up @@ -456,7 +456,7 @@ describe('uib-accordion', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}" is-open="group.open" class="testClass">{{group.content}}</uib-accordion-group>' +
'<div uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}" is-open="group.open" class="testClass">{{group.content}}</div>' +
'</uib-accordion>';
element = angular.element(tpl);
scope.groups = [
Expand All @@ -480,7 +480,7 @@ describe('uib-accordion', function() {
beforeEach(function() {
var tpl =
'<uib-accordion>' +
'<uib-accordion-group heading="title 1" is-disabled="disabled">Content 1</uib-accordion-group>' +
'<div uib-accordion-group heading="title 1" is-disabled="disabled">Content 1</div>' +
'</uib-accordion>';
element = angular.element(tpl);
scope.disabled = true;
Expand Down Expand Up @@ -519,10 +519,10 @@ describe('uib-accordion', function() {
function isDisabledStyleCheck() {
var tpl =
'<uib-accordion ng-init="a = [1,2,3]">' +
'<uib-accordion-group heading="I get overridden" is-disabled="true">' +
'<div uib-accordion-group heading="I get overridden" is-disabled="true">' +
'<uib-accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </uib-accordion-heading>' +
'Body' +
'</uib-accordion-group>' +
'</div>' +
'</uib-accordion>';
scope.disabled = true;
element = $compile(tpl)(scope);
Expand All @@ -536,10 +536,10 @@ describe('uib-accordion', function() {
beforeEach(function() {
var tpl =
'<uib-accordion ng-init="a = [1,2,3]">' +
'<uib-accordion-group heading="I get overridden">' +
'<div uib-accordion-group heading="I get overridden">' +
'<uib-accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </uib-accordion-heading>' +
'Body' +
'</uib-accordion-group>' +
'</div>' +
'</uib-accordion>';
element = $compile(tpl)(scope);
scope.$digest();
Expand All @@ -565,10 +565,10 @@ describe('uib-accordion', function() {
beforeEach(function() {
var tpl =
'<uib-accordion ng-init="a = [1,2,3]">' +
'<uib-accordion-group heading="I get overridden">' +
'<div uib-accordion-group heading="I get overridden">' +
'<div uib-accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </div>' +
'Body' +
'</uib-accordion-group>' +
'</div>' +
'</uib-accordion>';
element = $compile(tpl)(scope);
scope.$digest();
Expand All @@ -588,7 +588,7 @@ describe('uib-accordion', function() {

describe('uib-accordion-heading, with repeating uib-accordion-groups', function() {
it('should clone the uib-accordion-heading for each group', function() {
element = $compile('<uib-accordion><uib-accordion-group ng-repeat="x in [1,2,3]"><uib-accordion-heading>{{x}}</uib-accordion-heading></uib-accordion-group></uib-accordion>')(scope);
element = $compile('<uib-accordion><div uib-accordion-group ng-repeat="x in [1,2,3]"><uib-accordion-heading>{{x}}</uib-accordion-heading></div></uib-accordion>')(scope);
scope.$digest();
groups = element.find('.panel');
expect(groups.length).toBe(3);
Expand All @@ -600,7 +600,7 @@ describe('uib-accordion', function() {

describe('uib-accordion-heading attribute, with repeating uib-accordion-groups', function() {
it('should clone the uib-accordion-heading for each group', function() {
element = $compile('<uib-accordion><uib-accordion-group ng-repeat="x in [1,2,3]"><div uib-accordion-heading>{{x}}</div></uib-accordion-group></uib-accordion>')(scope);
element = $compile('<uib-accordion><div uib-accordion-group ng-repeat="x in [1,2,3]"><div uib-accordion-heading>{{x}}</div></div></uib-accordion>')(scope);
scope.$digest();
groups = element.find('.panel');
expect(groups.length).toBe(3);
Expand All @@ -614,46 +614,11 @@ describe('uib-accordion', function() {
it('should transclude heading to a template using data-uib-accordion-header', inject(function($templateCache) {
$templateCache.put('foo/bar.html', '<div class="panel"><a uib-accordion-transclude="heading" class="accordion-toggle"><span data-uib-accordion-header></span></a><div ng-transclude></div></div>');

element = $compile('<uib-accordion><uib-accordion-group template-url="foo/bar.html"><uib-accordion-heading>baz</uib-accordion-heading></uib-accordion-group></uib-accordion>')(scope);
element = $compile('<uib-accordion><div uib-accordion-group template-url="foo/bar.html"><uib-accordion-heading>baz</uib-accordion-heading></div></uib-accordion>')(scope);
scope.$digest();
groups = element.find('.panel');
expect(findGroupLink(0).text()).toBe('baz');
}));
});

describe('uib-accordion group panel class', function() {
it('should use the default value when panel class is falsy - #3968', function() {
element = $compile('<uib-accordion><uib-accordion-group heading="Heading">Content</uib-accordion-group></uib-accordion>')(scope);
scope.$digest();
groups = element.find('.panel');
expect(groups.eq(0)).toHaveClass('panel-default');

element = $compile('<uib-accordion><uib-accordion-group heading="Heading" panel-class="">Content</uib-accordion-group></uib-accordion>')(scope);
scope.$digest();
groups = element.find('.panel');
expect(groups.eq(0)).toHaveClass('panel-default');
});

it('should use the specified value when not falsy - #3968', function() {
element = $compile('<uib-accordion><uib-accordion-group heading="Heading" panel-class="custom-class">Content</uib-accordion-group></uib-accordion>')(scope);
scope.$digest();
groups = element.find('.panel');
expect(groups.eq(0)).toHaveClass('custom-class');
expect(groups.eq(0)).not.toHaveClass('panel-default');
});

it('should change class if panel-class is changed', function() {
element = $compile('<uib-accordion><uib-accordion-group heading="Heading" panel-class="{{panelClass}}">Content</uib-accordion-group></uib-accordion>')(scope);
scope.panelClass = 'custom-class';
scope.$digest();
groups = element.find('.panel');
expect(groups.eq(0)).toHaveClass('custom-class');

scope.panelClass = 'different-class';
scope.$digest();
expect(groups.eq(0)).toHaveClass('different-class');
expect(groups.eq(0)).not.toHaveClass('custom-class');
});
});
});
});
16 changes: 7 additions & 9 deletions template/accordion/accordion-group.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<div class="panel" ng-class="panelClass || 'panel-default'">
<div role="tab" id="{{::headingId}}" aria-selected="{{isOpen}}" class="panel-heading" ng-keypress="toggleOpen($event)">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" href aria-expanded="{{isOpen}}" aria-controls="{{::panelId}}" tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span uib-accordion-header ng-class="{'text-muted': isDisabled}">{{heading}}</span></a>
</h4>
</div>
<div id="{{::panelId}}" aria-labelledby="{{::headingId}}" aria-hidden="{{!isOpen}}" role="tabpanel" class="panel-collapse collapse" uib-collapse="!isOpen">
<div class="panel-body" ng-transclude></div>
</div>
<div role="tab" id="{{::headingId}}" aria-selected="{{isOpen}}" class="panel-heading" ng-keypress="toggleOpen($event)">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" href aria-expanded="{{isOpen}}" aria-controls="{{::panelId}}" tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span uib-accordion-header ng-class="{'text-muted': isDisabled}">{{heading}}</span></a>
</h4>
</div>
<div id="{{::panelId}}" aria-labelledby="{{::headingId}}" aria-hidden="{{!isOpen}}" role="tabpanel" class="panel-collapse collapse" uib-collapse="!isOpen">
<div class="panel-body" ng-transclude></div>
</div>

0 comments on commit 3819bbe

Please sign in to comment.