Skip to content

Commit

Permalink
fix(expansion-panel): toggle not being updated when set programmatica…
Browse files Browse the repository at this point in the history
…lly (#5650)

* fix(expansion-panel): toggle not being updated when set programmatically

Fixes the toggle arrow not being flipped when the `expanded` is set programmatically, in addition to the `hideToggle` input not working either. This is a regression from #5549 and is a consequence of the fact that the panel header reaches into the panel to determine what to do with the arrow.

Fixes #5623.

* chore: add a couple of unit tests for the fixes
  • Loading branch information
crisbeto authored and andrewseguin committed Jul 28, 2017
1 parent 66e222f commit 41c804b
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 4 deletions.
4 changes: 3 additions & 1 deletion src/lib/expansion/accordion-item.ts
Expand Up @@ -35,8 +35,10 @@ export class AccordionItem implements OnDestroy {
@Output() destroyed = new EventEmitter<void>();
/** The unique MdAccordionChild id. */
readonly id = `cdk-accordion-child-${nextId++}`;

/** Whether the MdAccordionChild is expanded. */
@Input() get expanded(): boolean { return this._expanded; }
@Input()
get expanded(): boolean { return this._expanded; }
set expanded(expanded: boolean) {
// Only emit events and update the internal value if the value changes.
if (this._expanded !== expanded) {
Expand Down
30 changes: 28 additions & 2 deletions src/lib/expansion/expansion-panel-header.ts
Expand Up @@ -12,6 +12,8 @@ import {
Host,
ViewEncapsulation,
ChangeDetectionStrategy,
ChangeDetectorRef,
OnDestroy,
} from '@angular/core';
import {
trigger,
Expand All @@ -22,6 +24,9 @@ import {
} from '@angular/animations';
import {SPACE, ENTER} from '../core/keyboard/keycodes';
import {MdExpansionPanel, EXPANSION_PANEL_ANIMATION_TIMING} from './expansion-panel';
import {filter} from '../core/rxjs/index';
import {merge} from 'rxjs/observable/merge';
import {Subscription} from 'rxjs/Subscription';


/**
Expand Down Expand Up @@ -62,8 +67,22 @@ import {MdExpansionPanel, EXPANSION_PANEL_ANIMATION_TIMING} from './expansion-pa
]),
],
})
export class MdExpansionPanelHeader {
constructor(@Host() public panel: MdExpansionPanel) {}
export class MdExpansionPanelHeader implements OnDestroy {
private _parentChangeSubscription: Subscription | null = null;

constructor(
@Host() public panel: MdExpansionPanel,
private _changeDetectorRef: ChangeDetectorRef) {

// Since the toggle state depends on an @Input on the panel, we
// need to subscribe and trigger change detection manually.
this._parentChangeSubscription = merge(
panel.opened,
panel.closed,
filter.call(panel._inputChanges, changes => !!changes.hideToggle)
)
.subscribe(() => this._changeDetectorRef.markForCheck());
}

/** Toggles the expanded state of the panel. */
_toggle(): void {
Expand Down Expand Up @@ -103,6 +122,13 @@ export class MdExpansionPanelHeader {
return;
}
}

ngOnDestroy() {
if (this._parentChangeSubscription) {
this._parentChangeSubscription.unsubscribe();
this._parentChangeSubscription = null;
}
}
}

/**
Expand Down
17 changes: 16 additions & 1 deletion src/lib/expansion/expansion-panel.ts
Expand Up @@ -16,6 +16,9 @@ import {
forwardRef,
ChangeDetectionStrategy,
ChangeDetectorRef,
SimpleChanges,
OnChanges,
OnDestroy,
} from '@angular/core';
import {
trigger,
Expand All @@ -27,6 +30,7 @@ import {
import {MdAccordion, MdAccordionDisplayMode} from './accordion';
import {AccordionItem} from './accordion-item';
import {UniqueSelectionDispatcher} from '../core';
import {Subject} from 'rxjs/Subject';


/** MdExpansionPanel's states. */
Expand Down Expand Up @@ -72,10 +76,13 @@ export const EXPANSION_PANEL_ANIMATION_TIMING = '225ms cubic-bezier(0.4,0.0,0.2,
]),
],
})
export class MdExpansionPanel extends AccordionItem {
export class MdExpansionPanel extends AccordionItem implements OnChanges, OnDestroy {
/** Whether the toggle indicator should be hidden. */
@Input() hideToggle: boolean = false;

/** Stream that emits for changes in `@Input` properties. */
_inputChanges = new Subject<SimpleChanges>();

constructor(@Optional() @Host() accordion: MdAccordion,
_changeDetectorRef: ChangeDetectorRef,
_uniqueSelectionDispatcher: UniqueSelectionDispatcher) {
Expand Down Expand Up @@ -104,6 +111,14 @@ export class MdExpansionPanel extends AccordionItem {
_getExpandedState(): MdExpansionPanelState {
return this.expanded ? 'expanded' : 'collapsed';
}

ngOnChanges(changes: SimpleChanges) {
this._inputChanges.next(changes);
}

ngOnDestroy() {
this._inputChanges.complete();
}
}

@Directive({
Expand Down
36 changes: 36 additions & 0 deletions src/lib/expansion/expansion.spec.ts
Expand Up @@ -103,12 +103,47 @@ describe('MdExpansionPanel', () => {
expect(styles.marginLeft).toBe('37px');
expect(styles.marginRight).toBe('37px');
}));

it('should be able to hide the toggle', () => {
const fixture = TestBed.createComponent(PanelWithContent);
const header = fixture.debugElement.query(By.css('.mat-expansion-panel-header')).nativeElement;

fixture.detectChanges();

expect(header.querySelector('.mat-expansion-indicator'))
.toBeTruthy('Expected indicator to be shown.');

fixture.componentInstance.hideToggle = true;
fixture.detectChanges();

expect(header.querySelector('.mat-expansion-indicator'))
.toBeFalsy('Expected indicator to be hidden.');
});

it('should update the indicator rotation when the expanded state is toggled programmatically',
fakeAsync(() => {
const fixture = TestBed.createComponent(PanelWithContent);

fixture.detectChanges();
tick(250);

const arrow = fixture.debugElement.query(By.css('.mat-expansion-indicator')).nativeElement;

expect(arrow.style.transform).toBe('rotate(0deg)', 'Expected no rotation.');

fixture.componentInstance.expanded = true;
fixture.detectChanges();
tick(250);

expect(arrow.style.transform).toBe('rotate(180deg)', 'Expected 180 degree rotation.');
}));
});


@Component({
template: `
<md-expansion-panel [expanded]="expanded"
[hideToggle]="hideToggle"
(opened)="openCallback()"
(closed)="closeCallback()">
<md-expansion-panel-header>Panel Title</md-expansion-panel-header>
Expand All @@ -118,6 +153,7 @@ describe('MdExpansionPanel', () => {
})
class PanelWithContent {
expanded: boolean = false;
hideToggle: boolean = false;
openCallback = jasmine.createSpy('openCallback');
closeCallback = jasmine.createSpy('closeCallback');
}
Expand Down

0 comments on commit 41c804b

Please sign in to comment.