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

Commit

Permalink
feat(accordion): enable HTML in accordion headings
Browse files Browse the repository at this point in the history
Defines a new directive <accordion-heading> that can be used below <accordion-group> elements to provide HTML to be transcluded into the group's heading.
The transcluded headfng is compiled and linked to the same scope as the transcluded body - so it can contain AngularJS directives itself.
  • Loading branch information
petebacondarwin authored and pkozlowski-opensource committed Mar 1, 2013
1 parent 6a97da2 commit 3afcaa4
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 12 deletions.
56 changes: 51 additions & 5 deletions src/accordion/accordion.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,29 +39,34 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
}
};

}]);
}])

// The accordion directive simply sets up the directive controller
// and adds an accordion CSS class to itself element.
angular.module('ui.bootstrap.accordion').directive('accordion', function () {
.directive('accordion', function () {
return {
restrict:'EA',
controller:'AccordionController',
transclude: true,
replace: false,
templateUrl: 'template/accordion/accordion.html'
};
});
})

// The accordion-group directive indicates a block of html that will expand and collapse in an accordion
angular.module('ui.bootstrap.accordion').directive('accordionGroup', ['$parse', '$transition', '$timeout', function($parse, $transition, $timeout) {
.directive('accordionGroup', ['$parse', '$transition', '$timeout', function($parse, $transition, $timeout) {
return {
require:'^accordion', // We need this directive to be inside an accordion
restrict:'EA',
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
templateUrl:'template/accordion/accordion-group.html',
scope:{ heading:'@' }, // Create an isolated scope and interpolate the heading attribute onto this scope
controller: function($scope) {
this.setHeading = function(element) {
this.heading = element;
};
},
link: function(scope, element, attrs, accordionCtrl) {
var getIsOpen, setIsOpen;

Expand Down Expand Up @@ -89,7 +94,48 @@ angular.module('ui.bootstrap.accordion').directive('accordionGroup', ['$parse',
setIsOpen(scope.$parent, value);
}
});
}
};
}])

// Use accordion-heading below an accordion-group to provide a heading containing HTML
// <accordion-group>
// <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
// </accordion-group>
.directive('accordionHeading', function() {
return {
restrict: 'E',
transclude: true, // Grab the contents to be used as the heading
template: '', // In effect remove this element!
replace: true,
require: '^accordionGroup',
compile: function(element, attr, transclude) {
return function link(scope, element, attr, accordionGroupCtrl) {
// Pass the heading to the accordion-group controller
// so that it can be transcluded into the right place in the template
// [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
accordionGroupCtrl.setHeading(transclude(scope, function() {}));
};
}
};
}]);
})

// Use in the accordion-group template to indicate where you want the heading to be transcluded
// You must provide the property on the accordion-group controller that will hold the transcluded element
// <div class="accordion-group">
// <div class="accordion-heading" ><a ... accordion-transclude="heading">...</a></div>
// ...
// </div>
.directive('accordionTransclude', function() {
return {
require: '^accordionGroup',
link: function(scope, element, attr, controller) {
scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) {
if ( heading ) {
element.html('');
element.append(heading);
}
});
}
};
});
50 changes: 44 additions & 6 deletions src/accordion/test/accordionSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,6 @@ describe('accordion', function () {
describe('accordion-group', function () {

var scope, $compile;

beforeEach(inject(function(_$rootScope_, _$compile_) {
scope = _$rootScope_;
$compile = _$compile_;
}));

var element, groups;
var findGroupLink = function (index) {
return groups.eq(index).find('a').eq(0);
Expand All @@ -118,6 +112,16 @@ describe('accordion', function () {
return groups.eq(index).find('.accordion-body').eq(0);
};


beforeEach(inject(function(_$rootScope_, _$compile_) {
scope = _$rootScope_;
$compile = _$compile_;
}));

afterEach(function () {
element = groups = scope = $compile = undefined;
});

describe('with static groups', function () {
beforeEach(function () {
var tpl =
Expand Down Expand Up @@ -257,5 +261,39 @@ describe('accordion', function () {
expect(findGroupBody(1)[0].clientHeight).toBe(0);
});
});

describe('accordion-heading element', function() {
beforeEach(function() {
var tpl =
'<accordion ng-init="a = [1,2,3]">' +
'<accordion-group heading="I get overridden">' +
'<accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </accordion-heading>' +
'Body' +
'</accordion-group>' +
'</accordion>';
element = $compile(tpl)(scope);
scope.$digest();
groups = element.find('.accordion-group');
});
it('transcludes the <accordion-heading> content into the heading link', function() {
expect(findGroupLink(0).text()).toBe('Heading Element 123 ');
});
it('attaches the same scope to the transcluded heading and body', function() {
expect(findGroupLink(0).find('span').scope().$id).toBe(findGroupBody(0).find('span').scope().$id);
});

});

describe('accordion-heading, with repeating accordion-groups', function() {
it('should clone the accordion-heading for each group', function() {
element = $compile('<accordion><accordion-group ng-repeat="x in [1,2,3]"><accordion-heading>{{x}}</accordion-heading></accordion-group></accordion>')(scope);
scope.$digest();
groups = element.find('.accordion-group');
expect(groups.length).toBe(3);
expect(findGroupLink(0).text()).toBe('1');
expect(findGroupLink(1).text()).toBe('2');
expect(findGroupLink(2).text()).toBe('3');
});
});
});
});
2 changes: 1 addition & 1 deletion template/accordion/accordion-group.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="accordion-group">
<div class="accordion-heading" ><a class="accordion-toggle" ng-click="isOpen = !isOpen">{{heading}}</a></div>
<div class="accordion-heading" ><a class="accordion-toggle" ng-click="isOpen = !isOpen" accordion-transclude="heading">{{heading}}</a></div>
<div class="accordion-body" collapse="!isOpen">
<div class="accordion-inner" ng-transclude></div> </div>
</div>

0 comments on commit 3afcaa4

Please sign in to comment.