diff --git a/src/accordion/accordion.js b/src/accordion/accordion.js index 9570d7ac66..421a118399 100644 --- a/src/accordion/accordion.js +++ b/src/accordion/accordion.js @@ -39,11 +39,11 @@ 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', @@ -51,10 +51,10 @@ angular.module('ui.bootstrap.accordion').directive('accordion', function () { 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', @@ -62,6 +62,11 @@ angular.module('ui.bootstrap.accordion').directive('accordionGroup', ['$parse', 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; @@ -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 +// +// Heading containing HTML - +// +.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 +//
+//
...
+// ... +//
+.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); + } + }); + } + }; +}); diff --git a/src/accordion/test/accordionSpec.js b/src/accordion/test/accordionSpec.js index 3d0d0becef..acad565a2f 100644 --- a/src/accordion/test/accordionSpec.js +++ b/src/accordion/test/accordionSpec.js @@ -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); @@ -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 = @@ -257,5 +261,39 @@ describe('accordion', function () { expect(findGroupBody(1)[0].clientHeight).toBe(0); }); }); + + describe('accordion-heading element', function() { + beforeEach(function() { + var tpl = + '' + + '' + + 'Heading Element {{x}} ' + + 'Body' + + '' + + ''; + element = $compile(tpl)(scope); + scope.$digest(); + groups = element.find('.accordion-group'); + }); + it('transcludes the 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('{{x}}')(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'); + }); + }); }); }); diff --git a/template/accordion/accordion-group.html b/template/accordion/accordion-group.html index df308a6d67..85e1a2a51b 100644 --- a/template/accordion/accordion-group.html +++ b/template/accordion/accordion-group.html @@ -1,5 +1,5 @@
- +
\ No newline at end of file