Skip to content

Commit b1fbadd

Browse files
Louw Swarthenetiriki
authored andcommitted
chore(accordion): adds disabled property to CDK accordion-item (#8141)
Adds a disabled property to Accordion Item in the CDK. Closes #8141
1 parent 4523556 commit b1fbadd

File tree

7 files changed

+134
-85
lines changed

7 files changed

+134
-85
lines changed

src/cdk/accordion/accordion-item.spec.ts

Lines changed: 112 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -31,55 +31,106 @@ describe('CdkAccordionItem', () => {
3131
.injector.get(CdkAccordionItem);
3232
});
3333

34-
it('should toggle its expanded state', () => {
35-
expect(item.expanded).toBe(false);
36-
item.toggle();
37-
expect(item.expanded).toBe(true);
38-
item.toggle();
39-
expect(item.expanded).toBe(false);
34+
describe('that is not disabled', () => {
35+
beforeEach(() => {
36+
item.disabled = false;
37+
});
38+
39+
it('should toggle its expanded state', () => {
40+
expect(item.expanded).toBe(false);
41+
item.toggle();
42+
expect(item.expanded).toBe(true);
43+
item.toggle();
44+
expect(item.expanded).toBe(false);
45+
});
46+
47+
it('should set its expanded state to expanded', () => {
48+
item.expanded = false;
49+
item.open();
50+
expect(item.expanded).toBe(true);
51+
});
52+
53+
it('should set its expanded state to closed', () => {
54+
item.expanded = true;
55+
item.close();
56+
expect(item.expanded).toBe(false);
57+
});
58+
59+
it('should emit a closed event', () => {
60+
item.open();
61+
fixture.detectChanges();
62+
spyOn(item.closed, 'emit');
63+
item.close();
64+
fixture.detectChanges();
65+
expect(item.closed.emit).toHaveBeenCalled();
66+
});
67+
68+
it('should not emit a closed event when the item is closed already', () => {
69+
expect(item.expanded).toBe(false);
70+
spyOn(item.closed, 'emit');
71+
item.close();
72+
fixture.detectChanges();
73+
expect(item.closed.emit).not.toHaveBeenCalled();
74+
});
75+
76+
it('should emit an opened event', () => {
77+
spyOn(item.opened, 'emit');
78+
item.open();
79+
fixture.detectChanges();
80+
expect(item.opened.emit).toHaveBeenCalled();
81+
});
82+
83+
it('should emit a destroyed event', () => {
84+
spyOn(item.destroyed, 'emit');
85+
item.ngOnDestroy();
86+
fixture.detectChanges();
87+
expect(item.destroyed.emit).toHaveBeenCalled();
88+
});
4089
});
4190

42-
it('should set its expanded state to expanded', () => {
43-
item.expanded = false;
44-
item.open();
45-
expect(item.expanded).toBe(true);
46-
});
47-
48-
it('should set its expanded state to closed', () => {
49-
item.expanded = true;
50-
item.close();
51-
expect(item.expanded).toBe(false);
52-
});
53-
54-
it('should emit a closed event', () => {
55-
item.open();
56-
fixture.detectChanges();
57-
spyOn(item.closed, 'emit');
58-
item.close();
59-
fixture.detectChanges();
60-
expect(item.closed.emit).toHaveBeenCalled();
61-
});
62-
63-
it('should not emit a closed event when the item is closed already', () => {
64-
expect(item.expanded).toBe(false);
65-
spyOn(item.closed, 'emit');
66-
item.close();
67-
fixture.detectChanges();
68-
expect(item.closed.emit).not.toHaveBeenCalled();
69-
});
70-
71-
it('should emit an opened event', () => {
72-
spyOn(item.opened, 'emit');
73-
item.open();
74-
fixture.detectChanges();
75-
expect(item.opened.emit).toHaveBeenCalled();
76-
});
77-
78-
it('should emit an destroyed event', () => {
79-
spyOn(item.destroyed, 'emit');
80-
item.ngOnDestroy();
81-
fixture.detectChanges();
82-
expect(item.destroyed.emit).toHaveBeenCalled();
91+
describe('that is disabled', () => {
92+
beforeEach(() => {
93+
item.disabled = true;
94+
});
95+
96+
it('should not toggle its expanded state', () => {
97+
expect(item.expanded).toBe(false);
98+
item.toggle();
99+
expect(item.expanded).toBe(false);
100+
});
101+
102+
it('should not set its expanded state to expanded', () => {
103+
item.expanded = false;
104+
item.open();
105+
expect(item.expanded).toBe(false);
106+
});
107+
108+
it('should not set its expanded state to closed', () => {
109+
item.expanded = true;
110+
item.close();
111+
expect(item.expanded).toBe(true);
112+
});
113+
114+
it('should not emit a closed event', () => {
115+
spyOn(item.closed, 'emit');
116+
item.close();
117+
fixture.detectChanges();
118+
expect(item.closed.emit).not.toHaveBeenCalled();
119+
});
120+
121+
it('should not emit an opened event', () => {
122+
spyOn(item.opened, 'emit');
123+
item.open();
124+
fixture.detectChanges();
125+
expect(item.opened.emit).not.toHaveBeenCalled();
126+
});
127+
128+
it('should emit a destroyed event', () => {
129+
spyOn(item.destroyed, 'emit');
130+
item.ngOnDestroy();
131+
fixture.detectChanges();
132+
expect(item.destroyed.emit).toHaveBeenCalled();
133+
});
83134
});
84135
});
85136

@@ -109,6 +160,20 @@ describe('CdkAccordionItem', () => {
109160
expect(firstItem.expanded).toBe(true);
110161
expect(secondItem.expanded).toBe(true);
111162
});
163+
164+
it('should not change expanded state for disabled items', () => {
165+
firstItem.disabled = true;
166+
expect(firstItem.expanded).toBe(false);
167+
expect(secondItem.expanded).toBe(false);
168+
firstItem.open();
169+
fixture.detectChanges();
170+
expect(firstItem.expanded).toBe(false);
171+
expect(secondItem.expanded).toBe(false);
172+
secondItem.open();
173+
fixture.detectChanges();
174+
expect(firstItem.expanded).toBe(false);
175+
expect(secondItem.expanded).toBe(true);
176+
});
112177
});
113178

114179

src/cdk/accordion/accordion-item.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ export class CdkAccordionItem implements OnDestroy {
6868
}
6969
private _expanded = false;
7070

71+
/** Whether the AccordionItem is disabled. */
72+
@Input()
73+
get disabled() { return this._disabled; }
74+
set disabled(disabled: any) { this._disabled = coerceBooleanProperty(disabled); }
75+
private _disabled: boolean = false;
76+
7177
/** Unregister function for _expansionDispatcher. */
7278
private _removeUniqueSelectionListener: () => void = () => {};
7379

@@ -91,16 +97,22 @@ export class CdkAccordionItem implements OnDestroy {
9197

9298
/** Toggles the expanded state of the accordion item. */
9399
toggle(): void {
94-
this.expanded = !this.expanded;
100+
if (!this.disabled) {
101+
this.expanded = !this.expanded;
102+
}
95103
}
96104

97105
/** Sets the expanded state of the accordion item to false. */
98106
close(): void {
99-
this.expanded = false;
107+
if (!this.disabled) {
108+
this.expanded = false;
109+
}
100110
}
101111

102112
/** Sets the expanded state of the accordion item to true. */
103113
open(): void {
104-
this.expanded = true;
114+
if (!this.disabled) {
115+
this.expanded = true;
116+
}
105117
}
106118
}

src/cdk/accordion/accordion.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export class CdkAccordion {
2323
/** A readonly id value to use for unique selection coordination. */
2424
readonly id = `cdk-accordion-${nextId++}`;
2525

26-
/** Whether the accordion should allow multiple expanded accordion items simulateously. */
26+
/** Whether the accordion should allow multiple expanded accordion items simultaneously. */
2727
@Input() get multi(): boolean { return this._multi; }
2828
set multi(multi: boolean) { this._multi = coerceBooleanProperty(multi); }
2929
private _multi: boolean = false;

src/cdk/accordion/public-api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
export {CdkAccordionItem} from './accordion-item';
9+
export {CdkAccordionItem} from './accordion-item';
1010
export {CdkAccordion} from './accordion';
1111
export * from './accordion-module';

src/lib/expansion/expansion-module.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ import {MatAccordion} from './accordion';
1616
import {MatExpansionPanelContent} from './expansion-panel-content';
1717
import {
1818
MatExpansionPanel,
19-
MatExpansionPanelActionRow,
20-
MatExpansionPanelBase
19+
MatExpansionPanelActionRow
2120
} from './expansion-panel';
2221
import {
2322
MatExpansionPanelDescription,
@@ -38,7 +37,6 @@ import {
3837
MatExpansionPanelContent,
3938
],
4039
declarations: [
41-
MatExpansionPanelBase,
4240
MatAccordion,
4341
MatExpansionPanel,
4442
MatExpansionPanelActionRow,

src/lib/expansion/expansion-panel-header.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,7 @@ export class MatExpansionPanelHeader implements OnDestroy {
9393

9494
/** Toggles the expanded state of the panel. */
9595
_toggle(): void {
96-
if (!this.panel.disabled) {
97-
this.panel.toggle();
98-
}
96+
this.panel.toggle();
9997
}
10098

10199
/** Gets whether the panel is expanded. */

src/lib/expansion/expansion-panel.ts

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
ChangeDetectorRef,
1212
Component,
1313
Directive,
14-
forwardRef,
1514
Host,
1615
Input,
1716
OnChanges,
@@ -25,7 +24,6 @@ import {
2524
} from '@angular/core';
2625
import {CdkAccordionItem} from '@angular/cdk/accordion';
2726
import {UniqueSelectionDispatcher} from '@angular/cdk/collections';
28-
import {CanDisable, mixinDisabled} from '@angular/material/core';
2927
import {TemplatePortal} from '@angular/cdk/portal';
3028
import {Subject} from 'rxjs/Subject';
3129
import {take} from 'rxjs/operators/take';
@@ -36,24 +34,6 @@ import {coerceBooleanProperty} from '@angular/cdk/coercion';
3634
import {MatExpansionPanelContent} from './expansion-panel-content';
3735
import {matExpansionAnimations} from './expansion-animations';
3836

39-
// Boilerplate for applying mixins to MatExpansionPanel.
40-
/** @docs-private */
41-
@Component({
42-
template: '',
43-
moduleId: module.id,
44-
encapsulation: ViewEncapsulation.None,
45-
preserveWhitespaces: false,
46-
changeDetection: ChangeDetectionStrategy.OnPush,
47-
})
48-
export class MatExpansionPanelBase extends CdkAccordionItem {
49-
constructor(accordion: MatAccordion,
50-
_changeDetectorRef: ChangeDetectorRef,
51-
_uniqueSelectionDispatcher: UniqueSelectionDispatcher) {
52-
super(accordion, _changeDetectorRef, _uniqueSelectionDispatcher);
53-
}
54-
}
55-
export const _MatExpansionPanelMixinBase = mixinDisabled(MatExpansionPanelBase);
56-
5737
/** MatExpansionPanel's states. */
5838
export type MatExpansionPanelState = 'expanded' | 'collapsed';
5939

@@ -81,14 +61,10 @@ export type MatExpansionPanelState = 'expanded' | 'collapsed';
8161
'class': 'mat-expansion-panel',
8262
'[class.mat-expanded]': 'expanded',
8363
'[class.mat-expansion-panel-spacing]': '_hasSpacing()',
84-
},
85-
providers: [
86-
{provide: _MatExpansionPanelMixinBase, useExisting: forwardRef(() => MatExpansionPanel)}
87-
],
64+
}
8865
})
89-
export class MatExpansionPanel extends _MatExpansionPanelMixinBase
90-
implements CanDisable, AfterContentInit, OnChanges, OnDestroy {
91-
66+
export class MatExpansionPanel extends CdkAccordionItem
67+
implements AfterContentInit, OnChanges, OnDestroy {
9268
/** Whether the toggle indicator should be hidden. */
9369
@Input()
9470
get hideToggle(): boolean {

0 commit comments

Comments
 (0)