diff --git a/src/cdk/accordion/accordion-item.ts b/src/cdk/accordion/accordion-item.ts
index 22f4a7f2cb61..2a020c0fc2a4 100644
--- a/src/cdk/accordion/accordion-item.ts
+++ b/src/cdk/accordion/accordion-item.ts
@@ -14,6 +14,7 @@ import {
OnDestroy,
Optional,
ChangeDetectorRef,
+ SkipSelf,
} from '@angular/core';
import {UniqueSelectionDispatcher} from '@angular/cdk/collections';
import {CdkAccordion} from './accordion';
@@ -30,6 +31,11 @@ let nextId = 0;
@Directive({
selector: 'cdk-accordion-item, [cdkAccordionItem]',
exportAs: 'cdkAccordionItem',
+ providers: [
+ // Provide CdkAccordion as undefined to prevent nested accordion items from registering
+ // to the same accordion.
+ {provide: CdkAccordion, useValue: undefined},
+ ],
})
export class CdkAccordionItem implements OnDestroy {
/** Subscription to openAll/closeAll events. */
@@ -90,7 +96,7 @@ export class CdkAccordionItem implements OnDestroy {
/** Unregister function for _expansionDispatcher. */
private _removeUniqueSelectionListener: () => void = () => {};
- constructor(@Optional() public accordion: CdkAccordion,
+ constructor(@Optional() @SkipSelf() public accordion: CdkAccordion,
private _changeDetectorRef: ChangeDetectorRef,
protected _expansionDispatcher: UniqueSelectionDispatcher) {
this._removeUniqueSelectionListener =
diff --git a/src/cdk/accordion/accordion.spec.ts b/src/cdk/accordion/accordion.spec.ts
index 4fd65bf86a60..7af1185d3f1b 100644
--- a/src/cdk/accordion/accordion.spec.ts
+++ b/src/cdk/accordion/accordion.spec.ts
@@ -12,7 +12,8 @@ describe('CdkAccordion', () => {
CdkAccordionModule
],
declarations: [
- SetOfItems
+ SetOfItems,
+ NestedItems,
],
});
TestBed.compileComponents();
@@ -53,6 +54,14 @@ describe('CdkAccordion', () => {
expect(firstPanel.expanded).toBeTruthy();
expect(secondPanel.expanded).toBeTruthy();
});
+
+ it('should not register nested items to the same accordion', () => {
+ const fixture = TestBed.createComponent(NestedItems);
+ const innerItem = fixture.componentInstance.innerItem;
+ const outerItem = fixture.componentInstance.outerItem;
+
+ expect(innerItem.accordion).not.toBe(outerItem.accordion);
+ });
});
@Component({template: `
@@ -65,3 +74,15 @@ class SetOfItems {
@ViewChild('item2') item2;
multi: boolean = false;
}
+
+
+@Component({template: `
+
+
+
+
+ `})
+class NestedItems {
+ @ViewChild('outerItem') outerItem: CdkAccordionItem;
+ @ViewChild('innerItem') innerItem: CdkAccordionItem;
+}
diff --git a/src/lib/expansion/accordion.spec.ts b/src/lib/expansion/accordion.spec.ts
index 6c12e2db42a4..f69022c1444d 100644
--- a/src/lib/expansion/accordion.spec.ts
+++ b/src/lib/expansion/accordion.spec.ts
@@ -2,10 +2,10 @@ import {async, TestBed} from '@angular/core/testing';
import {Component, ViewChild} from '@angular/core';
import {By} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
-import {MatExpansionModule, MatAccordion} from './index';
+import {MatExpansionModule, MatAccordion, MatExpansionPanel} from './index';
-describe('CdkAccordion', () => {
+describe('MatAccordion', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
@@ -13,7 +13,8 @@ describe('CdkAccordion', () => {
MatExpansionModule
],
declarations: [
- SetOfItems
+ NestedPanel,
+ SetOfItems,
],
});
TestBed.compileComponents();
@@ -84,6 +85,14 @@ describe('CdkAccordion', () => {
expect(panels[0].classes['mat-expanded']).toBeFalsy();
expect(panels[1].classes['mat-expanded']).toBeFalsy();
});
+
+ it('should not register nested panels to the same accordion', () => {
+ const fixture = TestBed.createComponent(NestedPanel);
+ const innerPanel = fixture.componentInstance.innerPanel;
+ const outerPanel = fixture.componentInstance.outerPanel;
+
+ expect(innerPanel.accordion).not.toBe(outerPanel.accordion);
+ });
});
@@ -106,3 +115,18 @@ class SetOfItems {
secondPanelExpanded: boolean = false;
secondPanelDisabled: boolean = false;
}
+
+@Component({template: `
+
+
+ Outer Panel
+
+ Inner Panel
+ Content
+
+
+ `})
+class NestedPanel {
+ @ViewChild('outerPanel') outerPanel: MatExpansionPanel;
+ @ViewChild('innerPanel') innerPanel: MatExpansionPanel;
+}
diff --git a/src/lib/expansion/expansion-panel.ts b/src/lib/expansion/expansion-panel.ts
index 63846745a44a..d7348f9da968 100644
--- a/src/lib/expansion/expansion-panel.ts
+++ b/src/lib/expansion/expansion-panel.ts
@@ -23,6 +23,7 @@ import {
OnDestroy,
Optional,
SimpleChanges,
+ SkipSelf,
ViewContainerRef,
ViewEncapsulation,
} from '@angular/core';
@@ -56,6 +57,11 @@ let uniqueId = 0;
inputs: ['disabled', 'expanded'],
outputs: ['opened', 'closed', 'expandedChange'],
animations: [matExpansionAnimations.bodyExpansion],
+ providers: [
+ // Provide MatAccordion as undefined to prevent nested expansion panels from registering
+ // to the same accordion.
+ {provide: MatAccordion, useValue: undefined},
+ ],
host: {
'class': 'mat-expansion-panel',
'[class.mat-expanded]': 'expanded',
@@ -87,7 +93,7 @@ export class MatExpansionPanel extends CdkAccordionItem
/** ID for the associated header element. Used for a11y labelling. */
_headerId = `mat-expansion-panel-header-${uniqueId++}`;
- constructor(@Optional() accordion: MatAccordion,
+ constructor(@Optional() @SkipSelf() accordion: MatAccordion,
_changeDetectorRef: ChangeDetectorRef,
_uniqueSelectionDispatcher: UniqueSelectionDispatcher,
private _viewContainerRef: ViewContainerRef) {