import { Component, Input, HostBinding, ElementRef, Output, KeyValueDiffers, KeyValueDiffer, EventEmitter, HostListener, ChangeDetectionStrategy, ChangeDetectorRef, DoCheck, SkipSelf } from '@angular/core'; import { columnsByPin, columnGroupWidths, columnsByPinArr, translateXY, Keys } from '../../utils'; import { ScrollbarHelper } from '../../services'; import { MouseEvent, KeyboardEvent, Event } from '../../events'; import { TreeStatus } from '../../index'; @Component({ selector: 'datatable-body-row', changeDetection: ChangeDetectionStrategy.OnPush, template: `
` }) export class DataTableBodyRowComponent implements DoCheck { @Input() set columns(val: any[]) { this._columns = val; this.recalculateColumns(val); this.buildStylesByGroup(); } get columns(): any[] { return this._columns; } @Input() set innerWidth(val: number) { if (this._columns) { const colByPin = columnsByPin(this._columns); this._columnGroupWidths = columnGroupWidths(colByPin, colByPin); } this._innerWidth = val; this.recalculateColumns(); this.buildStylesByGroup(); } get innerWidth(): number { return this._innerWidth; } @Input() expanded: boolean; @Input() rowClass: any; @Input() row: any; @Input() group: any; @Input() isSelected: boolean; @Input() rowIndex: number; @Input() displayCheck: any; @Input() treeStatus: TreeStatus = 'collapsed'; @Input() set offsetX(val: number) { this._offsetX = val; this.buildStylesByGroup(); } get offsetX() { return this._offsetX; } @HostBinding('class') get cssClass() { let cls = 'datatable-body-row'; if (this.isSelected) cls += ' active'; if (this.rowIndex % 2 !== 0) cls += ' datatable-row-odd'; if (this.rowIndex % 2 === 0) cls += ' datatable-row-even'; if (this.rowClass) { const res = this.rowClass(this.row); if (typeof res === 'string') { cls += ` ${res}`; } else if (typeof res === 'object') { const keys = Object.keys(res); for (const k of keys) { if (res[k] === true) cls += ` ${k}`; } } } return cls; } @HostBinding('style.height.px') @Input() rowHeight: number; @HostBinding('style.width.px') get columnsTotalWidths(): string { return this._columnGroupWidths.total; } @Output() activate: EventEmitter = new EventEmitter(); @Output() treeAction: EventEmitter = new EventEmitter(); _element: any; _columnGroupWidths: any; _columnsByPin: any; _offsetX: number; _columns: any[]; _innerWidth: number; _groupStyles = { left: {}, center: {}, right: {} }; private _rowDiffer: KeyValueDiffer<{}, {}>; constructor( private differs: KeyValueDiffers, @SkipSelf() private scrollbarHelper: ScrollbarHelper, private cd: ChangeDetectorRef, element: ElementRef) { this._element = element.nativeElement; this._rowDiffer = differs.find({}).create(); } ngDoCheck(): void { if (this._rowDiffer.diff(this.row)) { this.cd.markForCheck(); } } trackByGroups(index: number, colGroup: any): any { return colGroup.type; } columnTrackingFn(index: number, column: any): any { return column.$$id; } buildStylesByGroup() { this._groupStyles['left'] = this.calcStylesByGroup('left'); this._groupStyles['center'] = this.calcStylesByGroup('center'); this._groupStyles['right'] = this.calcStylesByGroup('right'); this.cd.markForCheck(); } calcStylesByGroup(group: string) { const widths = this._columnGroupWidths; const offsetX = this.offsetX; const styles = { width: `${widths[group]}px` }; if (group === 'left') { translateXY(styles, offsetX, 0); } else if (group === 'right') { const bodyWidth = parseInt(this.innerWidth + '', 0); const totalDiff = widths.total - bodyWidth; const offsetDiff = totalDiff - offsetX; const offset = (offsetDiff + this.scrollbarHelper.width) * -1; translateXY(styles, offset, 0); } return styles; } onActivate(event: any, index: number): void { event.cellIndex = index; event.rowElement = this._element; this.activate.emit(event); } @HostListener('keydown', ['$event']) onKeyDown(event: KeyboardEvent): void { const keyCode = event.keyCode; const isTargetRow = event.target === this._element; const isAction = keyCode === Keys.return || keyCode === Keys.down || keyCode === Keys.up || keyCode === Keys.left || keyCode === Keys.right; if (isAction && isTargetRow) { event.preventDefault(); event.stopPropagation(); this.activate.emit({ type: 'keydown', event, row: this.row, rowElement: this._element }); } } @HostListener('mouseenter', ['$event']) onMouseenter(event: any): void { this.activate.emit({ type: 'mouseenter', event, row: this.row, rowElement: this._element }); } recalculateColumns(val: any[] = this.columns): void { this._columns = val; const colsByPin = columnsByPin(this._columns); this._columnsByPin = columnsByPinArr(this._columns); this._columnGroupWidths = columnGroupWidths(colsByPin, this._columns); } onTreeAction() { this.treeAction.emit(); } }