Skip to content

Commit

Permalink
feat(accordion): add 'show' and 'hide' events (#4537)
Browse files Browse the repository at this point in the history
Fixes #4528
  • Loading branch information
maxokorokov committed Jul 6, 2023
1 parent 3bf60d5 commit 005290e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 5 deletions.
26 changes: 21 additions & 5 deletions src/accordion/accordion.directive.spec.ts
Expand Up @@ -74,12 +74,16 @@ function expectOpenPanels(nativeEl: HTMLElement, openPanelsDef: boolean[]) {
describe('ngb-accordion directive', () => {
let html = `
<div ngbAccordion #acc="ngbAccordion"
[closeOthers]="closeOthers" [destroyOnHide]="destroyOnHide" (shown)="shownCallback($event)" (hidden)="hiddenCallback($event)">
[closeOthers]="closeOthers" [destroyOnHide]="destroyOnHide"
(show)="showCallback($event)" (hide)="hideCallback($event)"
(shown)="shownCallback($event)" (hidden)="hiddenCallback($event)">
<div ngbAccordionItem *ngFor="let item of items"
[disabled]="item.disabled"
[collapsed]="item.collapsed"
[destroyOnHide]="item.destroyOnHide"
(show) = "itemShowCallback($event)"
(shown) = "itemShownCallback($event)"
(hide) = "itemHideCallback($event)"
(hidden) = "itemHiddenCallback($event)"
>
<h2 ngbAccordionHeader>
Expand Down Expand Up @@ -451,21 +455,29 @@ describe('ngb-accordion directive', () => {
const ci = fixture.componentInstance;
fixture.detectChanges();

spyOn(ci, 'showCallback');
spyOn(ci, 'shownCallback');
spyOn(ci, 'hideCallback');
spyOn(ci, 'hiddenCallback');
spyOn(ci, 'itemShowCallback');
spyOn(ci, 'itemShownCallback');
spyOn(ci, 'itemHideCallback');
spyOn(ci, 'itemHiddenCallback');

getButton(el, 0).click();
fixture.detectChanges();
const itemId = getItem(el, 0).id;

expect(fixture.componentInstance.showCallback).toHaveBeenCalledWith(itemId);
expect(fixture.componentInstance.shownCallback).toHaveBeenCalledWith(itemId);
expect(fixture.componentInstance.itemShowCallback).toHaveBeenCalledWith(undefined);
expect(fixture.componentInstance.itemShownCallback).toHaveBeenCalledWith(undefined);

getButton(el, 0).click();
fixture.detectChanges();
expect(fixture.componentInstance.hideCallback).toHaveBeenCalledWith(itemId);
expect(fixture.componentInstance.hiddenCallback).toHaveBeenCalledWith(itemId);
expect(fixture.componentInstance.itemHideCallback).toHaveBeenCalledWith(undefined);
expect(fixture.componentInstance.itemHiddenCallback).toHaveBeenCalledWith(undefined);
});

Expand Down Expand Up @@ -1149,8 +1161,12 @@ class TestComponent {
destroyOnHide: false,
},
];
shownCallback = (panelId: string) => {};
hiddenCallback = (panelId: string) => {};
itemShownCallback = (panelId?: string) => {};
itemHiddenCallback = (panelId?: string) => {};
showCallback = (_: string) => {};
shownCallback = (_: string) => {};
hideCallback = (_: string) => {};
hiddenCallback = (_: string) => {};
itemShowCallback = (_?) => {};
itemShownCallback = (_?) => {};
itemHideCallback = (_?) => {};
itemHiddenCallback = (_?) => {};
}
33 changes: 33 additions & 0 deletions src/accordion/accordion.directive.ts
Expand Up @@ -249,24 +249,46 @@ export class NgbAccordionItem implements AfterContentInit, OnDestroy {
return;
}

// changing the collapsed state
this._collapsed = collapsed;

this._cd.markForCheck(); // need if the accordion is used inside a component having OnPush change detection strategy
// we need force CD to get template into DOM before starting animation to calculate its height correctly
if (!this.collapsed) {
this.animatingBodyCollapse = true;
this._cd.detectChanges();
}

// firing events before starting animations
if (!this.collapsed) {
this.show.emit();
this._accordion.show.emit(this.id);
} else {
this.hide.emit();
this._accordion.hide.emit(this.id);
}

// we also need to make sure 'animation' flag is up-to- date
this._collapse.ngbCollapse.animation = this._accordion.animation;
this._collapse.ngbCollapse.collapsed = this.collapsed;
}
}

/**
* Event emitted before the expanding animation starts. It has no payload.
*/
@Output() show = new EventEmitter<void>();

/**
* Event emitted when the expanding animation is finished. It has no payload.
*/
@Output() shown = new EventEmitter<void>();

/**
* Event emitted before the collapsing animation starts. It has no payload.
*/
@Output() hide = new EventEmitter<void>();

/**
* Event emitted when the collapsing animation is finished and before the content is removed from DOM.
* It has no payload.
Expand Down Expand Up @@ -369,11 +391,22 @@ export class NgbAccordionDirective {
*/
@Input() destroyOnHide = true;

/**
* Event emitted before expanding animation starts and before content is added to the DOM.
* The payload is the id of shown accordion item.
*/
@Output() show = new EventEmitter<string>();

/**
* Event emitted when the expanding animation is finished. The payload is the id of shown accordion item.
*/
@Output() shown = new EventEmitter<string>();

/**
* Event emitted before the collapsing animation starts. The payload is the id of hidden accordion item.
*/
@Output() hide = new EventEmitter<string>();

/**
* Event emitted when the collapsing animation is finished and before the content is removed from DOM.
* The payload is the id of hidden accordion item.
Expand Down

0 comments on commit 005290e

Please sign in to comment.