import {
AfterContentInit,
ChangeDetectorRef,
Component,
ContentChild,
ElementRef,
EventEmitter,
HostBinding,
Inject,
Input,
Output,
} from "@angular/core";
import { IgxAngularAnimationService } from "../services/animation/angular-animation-service";
import { AnimationService } from "../services/animation/animation";
import { IgxExpansionPanelBodyComponent } from "./expansion-panel-body.component";
import { IgxExpansionPanelHeaderComponent } from "./expansion-panel-header.component";
import {
IExpansionPanelCancelableEventArgs,
IExpansionPanelEventArgs,
IgxExpansionPanelBase,
IGX_EXPANSION_PANEL_COMPONENT,
} from "./expansion-panel.common";
import {
ToggleAnimationPlayer,
ToggleAnimationSettings,
} from "./toggle-animation-component";
import { NgIf } from "@angular/common";
let NEXT_ID = 0;
@Component({
selector: "igx-expansion-panel",
templateUrl: "expansion-panel.component.html",
providers: [
{
provide: IGX_EXPANSION_PANEL_COMPONENT,
useExisting: IgxExpansionPanelComponent,
},
],
standalone: true,
imports: [NgIf],
})
export class IgxExpansionPanelComponent
extends ToggleAnimationPlayer
implements IgxExpansionPanelBase, AfterContentInit
{
/**
* Sets/gets the animation settings of the expansion panel component
* Open and Close animation should be passed
*
* Get
* ```typescript
* const currentAnimations = this.panel.animationSettings;
* ```
* Set
* ```typescript
* import { slideInLeft, slideOutRight } from 'igniteui-angular-sovn';
* ...
* this.panel.animationsSettings = {
* openAnimation: slideInLeft,
* closeAnimation: slideOutRight
* };
* ```
* or via template
* ```typescript
* import { slideInLeft, slideOutRight } from 'igniteui-angular-sovn';
* ...
* myCustomAnimationObject = {
* openAnimation: slideInLeft,
* closeAnimation: slideOutRight
* };
* ```html
*
* ...
*
* ```
*/
@Input()
public override get animationSettings(): ToggleAnimationSettings {
return this._animationSettings;
}
public override set animationSettings(value: ToggleAnimationSettings) {
this._animationSettings = value;
}
/**
* Sets/gets the `id` of the expansion panel component.
* If not set, `id` will have value `"igx-expansion-panel-0"`;
* ```html
*
* ```
* ```typescript
* let panelId = this.panel.id;
* ```
*
* @memberof IgxExpansionPanelComponent
*/
@HostBinding("attr.id")
@Input()
public id = `igx-expansion-panel-${NEXT_ID++}`;
/**
* @hidden
*/
@HostBinding("class.igx-expansion-panel")
public cssClass = "igx-expansion-panel";
/**
* @hidden
*/
@HostBinding("class.igx-expansion-panel--expanded")
private opened = false;
/**
* @hidden @internal
*/
@HostBinding("attr.aria-expanded")
public get panelExpanded() {
return !this.collapsed;
}
/**
* Gets/sets whether the component is collapsed (its content is hidden)
* Get
* ```typescript
* const myPanelState: boolean = this.panel.collapsed;
* ```
* Set
* ```html
* this.panel.collapsed = true;
* ```
*
* Two-way data binding:
* ```html
*
* ```
*/
@Input()
public collapsed = true;
/**
* @hidden
*/
@Output()
public collapsedChange = new EventEmitter();
/**
* Emitted when the expansion panel starts collapsing
* ```typescript
* handleCollapsing(event: IExpansionPanelCancelableEventArgs)
* ```
* ```html
*
* ...
*
* ```
*/
@Output()
public contentCollapsing =
new EventEmitter();
/**
* Emitted when the expansion panel finishes collapsing
* ```typescript
* handleCollapsed(event: IExpansionPanelEventArgs)
* ```
* ```html
*
* ...
*
* ```
*/
@Output()
public contentCollapsed = new EventEmitter();
/**
* Emitted when the expansion panel starts expanding
* ```typescript
* handleExpanding(event: IExpansionPanelCancelableEventArgs)
* ```
* ```html
*
* ...
*
* ```
*/
@Output()
public contentExpanding =
new EventEmitter();
/**
* Emitted when the expansion panel finishes expanding
* ```typescript
* handleExpanded(event: IExpansionPanelEventArgs)
* ```
* ```html
*
* ...
*
* ```
*/
@Output()
public contentExpanded = new EventEmitter();
/**
* @hidden
*/
public get headerId() {
return this.header ? `${this.id}-header` : "";
}
/**
* @hidden @internal
*/
public get nativeElement() {
return this.elementRef.nativeElement;
}
/**
* @hidden
*/
@ContentChild(IgxExpansionPanelBodyComponent, {
read: IgxExpansionPanelBodyComponent,
})
public body: IgxExpansionPanelBodyComponent;
/**
* @hidden
*/
@ContentChild(IgxExpansionPanelHeaderComponent, {
read: IgxExpansionPanelHeaderComponent,
})
public header: IgxExpansionPanelHeaderComponent;
constructor(
@Inject(IgxAngularAnimationService) animationService: AnimationService,
private cdr: ChangeDetectorRef,
private elementRef?: ElementRef
) {
super(animationService);
}
/** @hidden */
public ngAfterContentInit(): void {
if (this.body && this.header) {
// schedule at end of turn:
Promise.resolve().then(() => {
this.body.labelledBy = this.body.labelledBy || this.headerId;
this.body.label = this.body.label || this.id + "-region";
});
}
}
/**
* Collapses the panel
*
* ```html
*
* ...
*
*
* ```
*/
public collapse(evt?: Event) {
// If expansion panel is already collapsed or is collapsing, do nothing
if (this.collapsed || this.closeAnimationPlayer) {
return;
}
const args = { event: evt, panel: this, owner: this, cancel: false };
this.contentCollapsing.emit(args);
if (args.cancel === true) {
return;
}
this.opened = false;
this.playCloseAnimation(this.body?.element, () => {
this.contentCollapsed.emit({ event: evt, owner: this });
this.collapsed = true;
this.collapsedChange.emit(true);
this.cdr.markForCheck();
});
}
/**
* Expands the panel
*
* ```html
*
* ...
*
*
* ```
*/
public expand(evt?: Event) {
if (!this.collapsed) {
// If the panel is already opened, do nothing
return;
}
const args = { event: evt, panel: this, owner: this, cancel: false };
this.contentExpanding.emit(args);
if (args.cancel === true) {
return;
}
this.collapsed = false;
this.opened = true;
this.collapsedChange.emit(false);
this.cdr.detectChanges();
this.playOpenAnimation(this.body?.element, () => {
this.contentExpanded.emit({ event: evt, owner: this });
});
}
/**
* Toggles the panel
*
* ```html
*
* ...
*
*
* ```
*/
public toggle(evt?: Event) {
if (this.collapsed) {
this.open(evt);
} else {
this.close(evt);
}
}
public open(evt?: Event) {
this.expand(evt);
}
public close(evt?: Event) {
this.collapse(evt);
}
}