import {
Component,
ChangeDetectorRef,
ElementRef,
HostBinding,
HostListener,
Input,
Host,
EventEmitter,
Output,
ContentChild,
Inject,
ViewChild
} from '@angular/core';
import { IgxExpansionPanelIconDirective } from './expansion-panel.directives';
import { IGX_EXPANSION_PANEL_COMPONENT, IgxExpansionPanelBase, IExpansionPanelCancelableEventArgs } from './expansion-panel.common';
import { mkenum } from '../core/utils';
import { IgxIconComponent } from '../icon/icon.component';
import { NgIf } from '@angular/common';
/**
* @hidden
*/
export const ExpansionPanelHeaderIconPosition = mkenum({
LEFT: 'left',
NONE: 'none',
RIGHT: 'right'
});
export type ExpansionPanelHeaderIconPosition = (typeof ExpansionPanelHeaderIconPosition)[keyof typeof ExpansionPanelHeaderIconPosition];
@Component({
selector: 'igx-expansion-panel-header',
templateUrl: 'expansion-panel-header.component.html',
standalone: true,
imports: [NgIf, IgxIconComponent]
})
export class IgxExpansionPanelHeaderComponent {
/**
* Returns a reference to the `igx-expansion-panel-icon` element;
* If `iconPosition` is `NONE` - return null;
*/
public get iconRef(): ElementRef {
const renderedTemplate = this.customIconRef ?? this.defaultIconRef;
return this.iconPosition !== ExpansionPanelHeaderIconPosition.NONE ? renderedTemplate : null;
}
/**
* @hidden
*/
@ContentChild(IgxExpansionPanelIconDirective)
public set iconTemplate(val: boolean) {
this._iconTemplate = val;
}
/**
* @hidden
*/
public get iconTemplate(): boolean {
return this._iconTemplate;
}
/**
* Gets/sets the `aria-level` attribute of the header
* Get
* ```typescript
* const currentAriaLevel = this.panel.header.lv;
* ```
* Set
* ```typescript
* this.panel.header.lv = '5';
* ```
* ```html
*
* ```
*/
@HostBinding('attr.aria-level')
@Input()
public lv = '3';
/**
* Gets/sets the `role` attribute of the header
* Get
* ```typescript
* const currentRole = this.panel.header.role;
* ```
* Set
* ```typescript
* this.panel.header.role = '5';
* ```
* ```html
*
* ```
*/
@HostBinding('attr.role')
@Input()
public role = 'heading';
/**
* @hidden
*/
public get controls(): string {
return this.panel.id;
}
/**
* @hidden @internal
*/
public get innerElement() {
return this.elementRef.nativeElement.children[0];
}
/**
* Gets/sets the position of the expansion-panel-header expand/collapse icon
* Accepts `left`, `right` or `none`
* ```typescript
* const currentIconPosition = this.panel.header.iconPosition;
* ```
* Set
* ```typescript
* this.panel.header.iconPosition = 'left';
* ```
* ```html
*
* ```
*/
@Input()
public iconPosition: ExpansionPanelHeaderIconPosition = ExpansionPanelHeaderIconPosition.LEFT;
/**
* Emitted whenever a user interacts with the header host
* ```typescript
* handleInteraction(event: IExpansionPanelCancelableEventArgs) {
* ...
* }
* ```
* ```html
*
* ...
*
* ```
*/
@Output()
public interaction = new EventEmitter();
/**
* @hidden
*/
@HostBinding('class.igx-expansion-panel__header')
public cssClass = 'igx-expansion-panel__header';
/**
* @hidden
*/
@HostBinding('class.igx-expansion-panel__header--expanded')
public get isExpanded() {
return !this.panel.collapsed;
}
/**
* Gets/sets the whether the header is disabled
* When disabled, the header will not handle user events and will stop their propagation
*
* ```typescript
* const isDisabled = this.panel.header.disabled;
* ```
* Set
* ```typescript
* this.panel.header.disabled = true;
* ```
* ```html
*
* ...
*
* ```
*/
@Input()
@HostBinding('class.igx-expansion-panel--disabled')
public get disabled(): boolean {
return this._disabled;
}
public set disabled(val: boolean) {
this._disabled = val;
if (val) {
// V.S. June 11th, 2021: #9696 TabIndex should be removed when panel is disabled
delete this.tabIndex;
} else {
this.tabIndex = 0;
}
}
/** @hidden @internal */
@ContentChild(IgxExpansionPanelIconDirective, { read: ElementRef })
private customIconRef: ElementRef;
/** @hidden @internal */
@ViewChild(IgxIconComponent, { read: ElementRef })
private defaultIconRef: ElementRef;
/**
* Sets/gets the `id` of the expansion panel header.
* ```typescript
* let panelHeaderId = this.panel.header.id;
* ```
*
* @memberof IgxExpansionPanelComponent
*/
public id = '';
/** @hidden @internal */
public tabIndex = 0;
// properties section
private _iconTemplate = false;
private _disabled = false;
constructor(@Host() @Inject(IGX_EXPANSION_PANEL_COMPONENT) public panel: IgxExpansionPanelBase, public cdr: ChangeDetectorRef,
public elementRef: ElementRef) {
this.id = `${this.panel.id}-header`;
}
/**
* @hidden
*/
@HostListener('keydown.Enter', ['$event'])
@HostListener('keydown.Space', ['$event'])
@HostListener('keydown.Spacebar', ['$event'])
@HostListener('click', ['$event'])
public onAction(evt?: Event) {
if (this.disabled) {
evt.stopPropagation();
return;
}
const eventArgs: IExpansionPanelCancelableEventArgs = { event: evt, owner: this.panel, cancel: false };
this.interaction.emit(eventArgs);
if (eventArgs.cancel === true) {
return;
}
this.panel.toggle(evt);
evt.preventDefault();
}
/** @hidden @internal */
@HostListener('keydown.Alt.ArrowDown', ['$event'])
public openPanel(event: KeyboardEvent) {
if (event.altKey) {
const eventArgs: IExpansionPanelCancelableEventArgs = { event, owner: this.panel, cancel: false };
this.interaction.emit(eventArgs);
if (eventArgs.cancel === true) {
return;
}
this.panel.expand(event);
}
}
/** @hidden @internal */
@HostListener('keydown.Alt.ArrowUp', ['$event'])
public closePanel(event: KeyboardEvent) {
if (event.altKey) {
const eventArgs: IExpansionPanelCancelableEventArgs = { event, owner: this.panel, cancel: false };
this.interaction.emit(eventArgs);
if (eventArgs.cancel === true) {
return;
}
this.panel.collapse(event);
}
}
/**
* @hidden
*/
public get iconPositionClass(): string {
switch (this.iconPosition) {
case (ExpansionPanelHeaderIconPosition.LEFT):
return `igx-expansion-panel__header-icon--start`;
case (ExpansionPanelHeaderIconPosition.RIGHT):
return `igx-expansion-panel__header-icon--end`;
case (ExpansionPanelHeaderIconPosition.NONE):
return `igx-expansion-panel__header-icon--none`;
default:
return '';
}
}
}