Skip to content

Commit

Permalink
fix(accordion): properly determine titles when using nested accordions
Browse files Browse the repository at this point in the history
Fixes #2240

Closes #2247
  • Loading branch information
pkozlowski-opensource committed Mar 23, 2018
1 parent ca8d888 commit 171a70d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
29 changes: 29 additions & 0 deletions src/accordion/accordion.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,35 @@ describe('ngb-accordion', () => {
titles.forEach((title: HTMLElement, idx: number) => { expect(title.textContent.trim()).toBe(`Panel ${idx + 1}`); });
});

it('should not pick up titles from nested accordions', () => {
const testHtml = `
<ngb-accordion activeIds="open_me">
<ngb-panel title="parent title" id="open_me">
<ng-template ngbPanelContent>
<ngb-accordion>
<ngb-panel>
<ng-template ngbPanelTitle>child title</ng-template>
<ng-template ngbPanelContent>child content</ng-template>
</ngb-panel>
</ngb-accordion>
</ng-template>
</ngb-panel>
</ngb-accordion>
`;
const fixture = createTestComponent(testHtml);
// additional change detection is required to reproduce the problem in the test environment
fixture.detectChanges();

const titles = getPanelsTitle(fixture.nativeElement);
const parentTitle = titles[0].textContent.trim();
const childTitle = titles[1].textContent.trim();

expect(parentTitle).toContain('parent title');
expect(parentTitle).not.toContain('child title');
expect(childTitle).toContain('child title');
expect(childTitle).not.toContain('parent title');
});

it('should have the appropriate content', () => {
const fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
Expand Down
19 changes: 15 additions & 4 deletions src/accordion/accordion.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
AfterContentChecked,
Component,
ContentChild,
ContentChildren,
Directive,
EventEmitter,
Expand Down Expand Up @@ -38,7 +37,7 @@ export class NgbPanelContent {
* content
*/
@Directive({selector: 'ngb-panel'})
export class NgbPanel {
export class NgbPanel implements AfterContentChecked {
/**
* A flag determining whether the panel is disabled or not.
* When disabled, the panel cannot be toggled.
Expand Down Expand Up @@ -68,8 +67,20 @@ export class NgbPanel {
*/
@Input() type: string;

@ContentChild(NgbPanelContent) contentTpl: NgbPanelContent;
@ContentChild(NgbPanelTitle) titleTpl: NgbPanelTitle;
titleTpl: NgbPanelTitle | null;
contentTpl: NgbPanelContent | null;

@ContentChildren(NgbPanelTitle, {descendants: false}) titleTpls: QueryList<NgbPanelTitle>;
@ContentChildren(NgbPanelContent, {descendants: false}) contentTpls: QueryList<NgbPanelContent>;

ngAfterContentChecked() {
// We are using @ContentChildren instead of @ContantChild as in the Angular version being used
// only @ContentChildren allows us to specify the {descendants: false} option.
// Without {descendants: false} we are hitting bugs described in:
// https://github.com/ng-bootstrap/ng-bootstrap/issues/2240
this.titleTpl = this.titleTpls.first;
this.contentTpl = this.contentTpls.first;
}
}

/**
Expand Down

0 comments on commit 171a70d

Please sign in to comment.