diff --git a/projects/ngx-datatable/src/lib/components/body/body-cell.component.ts b/projects/ngx-datatable/src/lib/components/body/body-cell.component.ts index 693238fe3..0a28272c2 100644 --- a/projects/ngx-datatable/src/lib/components/body/body-cell.component.ts +++ b/projects/ngx-datatable/src/lib/components/body/body-cell.component.ts @@ -18,6 +18,11 @@ import { import { TableColumn } from '../../types/table-column.type'; import { SortDirection } from '../../types/sort-direction.type'; import { Keys } from '../../utils/keys'; +import { RowOrGroup } from "../../types/group.type"; +import { BehaviorSubject } from "rxjs"; +import { ActivateEvent } from '../../types/activate-event.type'; +import { CellContext } from '../../types/cell-context.type'; +import { SortPropDir } from '../../types/sort-prop-dir.type'; export type TreeStatus = 'collapsed' | 'expanded' | 'loading' | 'disabled'; @@ -70,11 +75,11 @@ export type TreeStatus = 'collapsed' | 'expanded' | 'loading' | 'disabled'; ` }) -export class DataTableBodyCellComponent implements DoCheck, OnDestroy { - @Input() displayCheck: (row: any, column?: TableColumn, value?: any) => boolean; +export class DataTableBodyCellComponent implements DoCheck, OnDestroy { + @Input() displayCheck: (row: RowOrGroup, column: TableColumn, value: any) => boolean; - _disable$; - @Input() set disable$(val: any) { + _disable$: BehaviorSubject; + @Input() set disable$(val: BehaviorSubject) { this._disable$ = val; this.cellContext.disable$ = val; }; @@ -82,7 +87,7 @@ export class DataTableBodyCellComponent implements DoCheck, OnDestroy { return this._disable$; } - @Input() set group(group: any) { + @Input() set group(group: TRow[]) { this._group = group; this.cellContext.group = group; this.checkValueUpdates(); @@ -146,23 +151,23 @@ export class DataTableBodyCellComponent implements DoCheck, OnDestroy { return this._column; } - @Input() set row(row: any) { + @Input() set row(row: RowOrGroup) { this._row = row; this.cellContext.row = row; this.checkValueUpdates(); this.cd.markForCheck(); } - get row(): any { + get row(): RowOrGroup { return this._row; } - @Input() set sorts(val: any[]) { + @Input() set sorts(val: SortPropDir[]) { this._sorts = val; - this.calcSortDir = this.calcSortDir(val); + this.sortDir = this.calcSortDir(val); } - get sorts(): any[] { + get sorts(): SortPropDir[] { return this._sorts; } @@ -183,7 +188,7 @@ export class DataTableBodyCellComponent implements DoCheck, OnDestroy { @Input() ghostLoadingIndicator = false; - @Output() activate: EventEmitter = new EventEmitter(); + @Output() activate: EventEmitter> = new EventEmitter(); @Output() treeAction: EventEmitter = new EventEmitter(); @@ -194,7 +199,7 @@ export class DataTableBodyCellComponent implements DoCheck, OnDestroy { ghostLoaderTemplate: ViewContainerRef; @HostBinding('class') - get columnCssClasses(): any { + get columnCssClasses(): string { let cls = 'datatable-body-cell'; if (this.column.cellClass) { if (typeof this.column.cellClass === 'string') { @@ -263,30 +268,28 @@ export class DataTableBodyCellComponent implements DoCheck, OnDestroy { return height + 'px'; } - sanitizedValue: any; + sanitizedValue: string; value: any; sortDir: SortDirection; isFocused = false; - onCheckboxChangeFn = this.onCheckboxChange.bind(this); - activateFn = this.activate.emit.bind(this.activate); - cellContext: any; + cellContext: CellContext; private _isSelected: boolean; - private _sorts: any[]; + private _sorts: SortPropDir[]; private _column: TableColumn; - private _row: any; - private _group: any; + private _row: RowOrGroup; + private _group: TRow[]; private _rowHeight: number; private _rowIndex: number; private _expanded: boolean; - private _element: any; + private _element: HTMLElement; private _treeStatus: TreeStatus; - constructor(element: ElementRef, private cd: ChangeDetectorRef) { + constructor(element: ElementRef, private cd: ChangeDetectorRef) { this.cellContext = { - onCheckboxChangeFn: this.onCheckboxChangeFn, - activateFn: this.activateFn, + onCheckboxChangeFn: (event: Event) => this.onCheckboxChange(event), + activateFn: (event: ActivateEvent) => this.activate.emit(event), row: this.row, group: this.group, value: this.value, @@ -296,7 +299,7 @@ export class DataTableBodyCellComponent implements DoCheck, OnDestroy { rowIndex: this.rowIndex, treeStatus: this.treeStatus, disable$: this.disable$, - onTreeAction: this.onTreeAction.bind(this) + onTreeAction: () => this.onTreeAction() }; this._element = element.nativeElement; @@ -407,7 +410,7 @@ export class DataTableBodyCellComponent implements DoCheck, OnDestroy { } } - onCheckboxChange(event: any): void { + onCheckboxChange(event: Event): void { this.activate.emit({ type: 'checkbox', event, @@ -421,15 +424,15 @@ export class DataTableBodyCellComponent implements DoCheck, OnDestroy { }); } - calcSortDir(sorts: any[]): any { + calcSortDir(sorts: SortPropDir[]): SortDirection { if (!sorts) { return; } - const sort = sorts.find((s: any) => s.prop === this.column.prop); + const sort = sorts.find(s => s.prop === this.column.prop); if (sort) { - return sort.dir; + return sort.dir as SortDirection; } } @@ -444,8 +447,8 @@ export class DataTableBodyCellComponent implements DoCheck, OnDestroy { this.treeAction.emit(this.row); } - calcLeftMargin(column: any, row: any) { + calcLeftMargin(column: TableColumn, row: RowOrGroup): number { const levelIndent = column.treeLevelIndent != null ? column.treeLevelIndent : 50; - return column.isTreeColumn ? row.level * levelIndent : 0; + return column.isTreeColumn ? (row as TRow).level * levelIndent : 0; } } diff --git a/projects/ngx-datatable/src/lib/components/body/body-group-header-template.directive.ts b/projects/ngx-datatable/src/lib/components/body/body-group-header-template.directive.ts index 4d2ad9ce8..3f499ef66 100644 --- a/projects/ngx-datatable/src/lib/components/body/body-group-header-template.directive.ts +++ b/projects/ngx-datatable/src/lib/components/body/body-group-header-template.directive.ts @@ -1,8 +1,14 @@ import { Directive, TemplateRef } from '@angular/core'; +import { GroupContext } from '../../types/cell-context.type'; @Directive({ selector: '[ngx-datatable-group-header-template]' }) -export class DatatableGroupHeaderTemplateDirective { - constructor(public template: TemplateRef) {} +export class DatatableGroupHeaderTemplateDirective { + static ngTemplateContextGuard( + directive: DatatableGroupHeaderTemplateDirective, + context: unknown + ): context is GroupContext { + return true; + } } diff --git a/projects/ngx-datatable/src/lib/components/body/body-group-header.directive.spec.ts b/projects/ngx-datatable/src/lib/components/body/body-group-header.directive.spec.ts index 18dbf23e4..cc5aaf71b 100644 --- a/projects/ngx-datatable/src/lib/components/body/body-group-header.directive.spec.ts +++ b/projects/ngx-datatable/src/lib/components/body/body-group-header.directive.spec.ts @@ -19,7 +19,6 @@ class TestFixtureComponent {} describe('DatatableGroupHeaderDirective', () => { let fixture: ComponentFixture; let component: TestFixtureComponent; - let element: any; // provide our implementations or mocks to the dependency injector beforeEach(() => { @@ -33,7 +32,6 @@ describe('DatatableGroupHeaderDirective', () => { TestBed.compileComponents().then(() => { fixture = TestBed.createComponent(TestFixtureComponent); component = fixture.componentInstance; - element = fixture.nativeElement; }); }) ); diff --git a/projects/ngx-datatable/src/lib/components/body/body-group-header.directive.ts b/projects/ngx-datatable/src/lib/components/body/body-group-header.directive.ts index 8994530d3..1b4b8cb4e 100644 --- a/projects/ngx-datatable/src/lib/components/body/body-group-header.directive.ts +++ b/projects/ngx-datatable/src/lib/components/body/body-group-header.directive.ts @@ -1,8 +1,9 @@ import { ContentChild, Directive, EventEmitter, Input, Output, TemplateRef } from '@angular/core'; import { DatatableGroupHeaderTemplateDirective } from './body-group-header-template.directive'; +import { GroupContext } from '../../types/cell-context.type'; @Directive({ selector: 'ngx-datatable-group-header' }) -export class DatatableGroupHeaderDirective { +export class DatatableGroupHeaderDirective { /** * Row height is required when virtual scroll is enabled. */ @@ -14,12 +15,12 @@ export class DatatableGroupHeaderDirective { @Input() checkboxable = false; @Input('template') - _templateInput: TemplateRef; + _templateInput: TemplateRef>; @ContentChild(DatatableGroupHeaderTemplateDirective, { read: TemplateRef, static: true }) - _templateQuery: TemplateRef; + _templateQuery: TemplateRef>; - get template(): TemplateRef { + get template(): TemplateRef> { return this._templateInput || this._templateQuery; } diff --git a/projects/ngx-datatable/src/lib/components/body/body-row-wrapper.component.ts b/projects/ngx-datatable/src/lib/components/body/body-row-wrapper.component.ts index 8df65704c..56e0a43e4 100644 --- a/projects/ngx-datatable/src/lib/components/body/body-row-wrapper.component.ts +++ b/projects/ngx-datatable/src/lib/components/body/body-row-wrapper.component.ts @@ -17,7 +17,13 @@ import { ViewChild } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; +import { Group, RowOrGroup } from '../../types/group.type'; +import { NgStyle } from '@angular/common'; import { DatatableComponentToken } from '../../utils/table-token'; +import { RowDetailContext } from '../../types/detail-context.type'; +import { GroupContext } from '../../types/cell-context.type'; +import { DatatableGroupHeaderDirective } from './body-group-header.directive'; +import { DatatableRowDetailDirective } from '../row-detail/row-detail.directive'; @Component({ selector: 'datatable-row-wrapper', @@ -34,7 +40,7 @@ import { DatatableComponentToken } from '../../utils/table-token'; implements DoCheck, OnInit { @ViewChild('select') checkBoxInput!: ElementRef; @Input() innerWidth: number; - @Input() rowDetail: any; - @Input() groupHeader: any; + @Input() rowDetail: DatatableRowDetailDirective; + @Input() groupHeader: DatatableGroupHeaderDirective; @Input() offsetX: number; - @Input() detailRowHeight: any; + @Input() detailRowHeight: number; @Input() groupHeaderRowHeight: number; - @Input() row: any; - @Input() groupedRows: any; - @Input() disableCheck: (row: any) => boolean; - @Input() selected: any[]; - @Output() rowContextmenu = new EventEmitter<{ event: MouseEvent; row: any }>(false); + @Input() row: RowOrGroup; + @Input() groupedRows: Group[]; + @Input() disableCheck: (row: RowOrGroup) => boolean; + @Input() selected: TRow[]; + @Output() rowContextmenu = new EventEmitter<{ event: MouseEvent; row: RowOrGroup }>(false); @Input() set rowIndex(val: number) { this._rowIndex = val; @@ -89,7 +95,7 @@ export class DataTableRowWrapperComponent implements DoCheck, OnInit { return this._rowIndex; } - selectedGroupRows = []; + selectedGroupRows: TRow[] = []; @Input() set expanded(val: boolean) { this._expanded = val; @@ -102,18 +108,18 @@ export class DataTableRowWrapperComponent implements DoCheck, OnInit { return this._expanded; } - groupContext: any; - rowContext: any; + groupContext: GroupContext; + rowContext: RowDetailContext; disable$: BehaviorSubject; - private rowDiffer: KeyValueDiffer; - private selectedRowsDiffer: IterableDiffer; + private rowDiffer: KeyValueDiffer, any>; + private selectedRowsDiffer: IterableDiffer; private _expanded = false; private _rowIndex: number; private tableComponent = inject(DatatableComponentToken); - constructor(private cd: ChangeDetectorRef, private differs: KeyValueDiffers, private iterableDiffers: IterableDiffers) { + constructor(private cd: ChangeDetectorRef, differs: KeyValueDiffers, private iterableDiffers: IterableDiffers) { this.groupContext = { group: this.row, expanded: this.expanded, @@ -123,27 +129,39 @@ export class DataTableRowWrapperComponent implements DoCheck, OnInit { this.rowContext = { row: this.row, expanded: this.expanded, - rowIndex: this.rowIndex + rowIndex: this.rowIndex, + disableRow$: this.disable$ }; this.rowDiffer = differs.find({}).create(); this.selectedRowsDiffer = this.iterableDiffers.find(this.selected ?? []).create(); } + get group(): Group { + if (typeof this.row === 'object' && 'value' in this.row) { + return this.row; + } else { + throw new Error('Row is not a group'); + } + } + ngOnInit(): void { if (this.disableCheck) { const isRowDisabled = this.disableCheck(this.row); this.disable$ = new BehaviorSubject(isRowDisabled); + this.rowContext.disableRow$ = this.disable$; } - this.rowContext.disableRow$ = this.disable$; } ngDoCheck(): void { if (this.disableCheck) { const isRowDisabled = this.disableCheck(this.row); - this.disable$.next(isRowDisabled); - this.cd.markForCheck(); + if (isRowDisabled !== this.disable$.value) { + this.disable$.next(isRowDisabled); + this.cd.markForCheck(); + } } + if (this.rowDiffer.diff(this.row)) { this.rowContext.row = this.row; this.groupContext.group = this.row; @@ -154,9 +172,9 @@ export class DataTableRowWrapperComponent implements DoCheck, OnInit { // if any of the row of this group is not present in `selected` rows array // mark group header checkbox state as indeterminate if (this.groupHeader?.checkboxable && this.selectedRowsDiffer.diff(this.selected)) { - const selectedRows = this.selected.filter(row => this.row.value.find(item => item === row)); + const selectedRows = this.selected.filter(row => this.group.value.find(item => item === row)); if (this.checkBoxInput) { - if (selectedRows.length && selectedRows.length !== this.row.value.length) { + if (selectedRows.length && selectedRows.length !== this.group.value.length) { this.checkBoxInput.nativeElement.indeterminate = true; } else { this.checkBoxInput.nativeElement.indeterminate = false; @@ -171,21 +189,20 @@ export class DataTableRowWrapperComponent implements DoCheck, OnInit { this.rowContextmenu.emit({ event: $event, row: this.row }); } - getGroupHeaderStyle(): any { - const styles = {} as any; - - styles.transform = 'translate3d(' + this.offsetX + 'px, 0px, 0px)'; - styles['backface-visibility'] = 'hidden'; - styles.width = this.innerWidth + 'px'; - return styles; + getGroupHeaderStyle(): NgStyle['ngStyle'] { + return { + "transform": 'translate3d(' + this.offsetX + 'px, 0px, 0px)', + 'backface-visibility': 'hidden', + "width": this.innerWidth + 'px' + }; } onCheckboxChange(groupSelected: boolean): void { // First remove all rows of this group from `selected` - this.selected = [...this.selected.filter(row => !this.row.value.find(item => item === row))]; + this.selected = [...this.selected.filter(row => !this.group.value.find(item => item === row))]; // If checkbox is checked then add all rows of this group in `selected` if (groupSelected) { - this.selected = [...this.selected, ...this.row.value]; + this.selected = [...this.selected, ...this.group.value]; } // Update `selected` of DatatableComponent with newly evaluated `selected` this.tableComponent.selected = [...this.selected]; diff --git a/projects/ngx-datatable/src/lib/components/body/body-row.component.ts b/projects/ngx-datatable/src/lib/components/body/body-row.component.ts index e133b91d6..0dcfbec75 100644 --- a/projects/ngx-datatable/src/lib/components/body/body-row.component.ts +++ b/projects/ngx-datatable/src/lib/components/body/body-row.component.ts @@ -22,7 +22,11 @@ import { Keys } from '../../utils/keys'; import { ScrollbarHelper } from '../../services/scrollbar-helper.service'; import { translateXY } from '../../utils/translate'; import { BehaviorSubject } from 'rxjs'; -import { DataTableRowWrapperComponent } from './body-row-wrapper.component'; +import { RowOrGroup } from "../../types/group.type"; +import { NgStyle } from '@angular/common'; +import { TableColumn } from '../../types/table-column.type'; +import { PinnedColumns } from '../../types/column-pin.type'; +import { ColumnGroupWidth } from '../../types/column-group-width.type'; @Component({ selector: 'datatable-body-row', @@ -56,8 +60,8 @@ import { DataTableRowWrapperComponent } from './body-row-wrapper.component'; ` }) -export class DataTableBodyRowComponent implements DoCheck, OnChanges { - @Input() set columns(val: any[]) { +export class DataTableBodyRowComponent implements DoCheck, OnChanges { + @Input() set columns(val: TableColumn[]) { this._columns = val; this.recalculateColumns(val); this.buildStylesByGroup(); @@ -83,13 +87,13 @@ export class DataTableBodyRowComponent implements DoCheck, OnChanges { } @Input() expanded: boolean; - @Input() rowClass: any; - @Input() row: any; - @Input() group: any; + @Input() rowClass?: (row: RowOrGroup) => string | Record; + @Input() row: RowOrGroup; + @Input() group: TRow[]; @Input() isSelected: boolean; @Input() rowIndex: number; - @Input() displayCheck: any; - @Input() treeStatus: TreeStatus = 'collapsed'; + @Input() displayCheck: (row: TRow, column: TableColumn, value?: any) => boolean; + @Input() treeStatus?: TreeStatus = 'collapsed'; @Input() ghostLoadingIndicator = false; @Input() verticalScrollVisible = false; @@ -141,32 +145,32 @@ export class DataTableBodyRowComponent implements DoCheck, OnChanges { rowHeight: number; @HostBinding('style.width.px') - get columnsTotalWidths(): string { + get columnsTotalWidths(): number { return this._columnGroupWidths.total; } @Output() activate: EventEmitter = new EventEmitter(); @Output() treeAction: EventEmitter = new EventEmitter(); - _element: any; - _columnGroupWidths: any; - _columnsByPin: any; + _element: HTMLElement; + _columnGroupWidths: ColumnGroupWidth; + _columnsByPin: PinnedColumns[]; _offsetX: number; - _columns: any[]; + _columns: TableColumn[]; _innerWidth: number; - _groupStyles: { [prop: string]: unknown } = { - left: {}, - center: {}, - right: {} - }; + _groupStyles: { + left: NgStyle['ngStyle'], + center: NgStyle['ngStyle'], + right: NgStyle['ngStyle'] + } = { left: {}, center: {}, right: {} }; - private _rowDiffer: KeyValueDiffer; + private _rowDiffer: KeyValueDiffer, any>; constructor( - private differs: KeyValueDiffers, + differs: KeyValueDiffers, @SkipSelf() private scrollbarHelper: ScrollbarHelper, private cd: ChangeDetectorRef, - element: ElementRef + element: ElementRef ) { this._element = element.nativeElement; this._rowDiffer = differs.find({}).create(); @@ -184,11 +188,11 @@ export class DataTableBodyRowComponent implements DoCheck, OnChanges { } } - trackByGroups(index: number, colGroup: any): any { + trackByGroups(index: number, colGroup: PinnedColumns): string { return colGroup.type; } - columnTrackingFn(index: number, column: any): any { + columnTrackingFn(index: number, column: TableColumn): string { return column.$$id; } @@ -199,25 +203,29 @@ export class DataTableBodyRowComponent implements DoCheck, OnChanges { this.cd.markForCheck(); } - calcStylesByGroup(group: string) { + calcStylesByGroup(group: 'left' | 'right' | 'center') { const widths = this._columnGroupWidths; const offsetX = this.offsetX; - const styles = { - width: `${widths[group]}px` - }; - if (group === 'left') { - translateXY(styles, offsetX, 0); + return { + width: `${widths[group]}px`, + ...translateXY(offsetX, 0) + } } else if (group === 'right') { const bodyWidth = this.innerWidth; const totalDiff = widths.total - bodyWidth; const offsetDiff = totalDiff - offsetX; const offset = (offsetDiff + (this.verticalScrollVisible ? this.scrollbarHelper.width : 0)) * -1; - translateXY(styles, offset, 0); + return { + width: `${widths[group]}px`, + ...translateXY(offset, 0) + } } - return styles; + return { + width: `${widths[group]}px` + }; } onActivate(event: any, index: number): void { @@ -263,7 +271,7 @@ export class DataTableBodyRowComponent implements DoCheck, OnChanges { }); } - recalculateColumns(val: any[] = this.columns): void { + recalculateColumns(val: TableColumn[] = this.columns): void { this._columns = val; const colsByPin = columnsByPin(this._columns); this._columnsByPin = columnsByPinArr(this._columns); diff --git a/projects/ngx-datatable/src/lib/components/body/body.component.ts b/projects/ngx-datatable/src/lib/components/body/body.component.ts index 03b97c7c4..1b6901e08 100644 --- a/projects/ngx-datatable/src/lib/components/body/body.component.ts +++ b/projects/ngx-datatable/src/lib/components/body/body.component.ts @@ -9,6 +9,7 @@ import { OnInit, Output, TemplateRef, + TrackByFunction, ViewChild } from '@angular/core'; import { ScrollerComponent } from './scroller.component'; @@ -17,6 +18,17 @@ import { columnGroupWidths, columnsByPin } from '../../utils/column'; import { RowHeightCache } from '../../utils/row-height-cache'; import { translateXY } from '../../utils/translate'; import { DragEventData } from '../../types/drag-events.type'; +import { TreeStatus } from "./body-cell.component"; +import { Group, RowOrGroup } from "../../types/group.type"; +import { NgClass, NgStyle } from '@angular/common'; +import { TableColumn } from '../../types/table-column.type'; +import { Model } from './selection.component'; +import { BodyPageEvent } from '../../types/page-event.type'; +import { DatatableGroupHeaderDirective } from './body-group-header.directive'; +import { DatatableRowDetailDirective } from '../row-detail/row-detail.directive'; +import { DataTableBodyRowComponent } from './body-row.component'; +import { ScrollEvent } from '../../types/scroll.type'; +import { ColumnGroupWidth } from '../../types/column-group-width.type'; @Component({ selector: 'datatable-body', @@ -99,7 +111,7 @@ import { DragEventData } from '../../types/drag-events.type'; - + - +
-
- -
- + class="empty-row" + *ngIf="!customEmptyContent?.children.length" + [innerHTML]="emptyMessage" + > +
+ +
`, @@ -198,7 +209,7 @@ import { DragEventData } from '../../types/drag-events.type'; class: 'datatable-body' } }) -export class DataTableBodyComponent implements OnInit, OnDestroy { +export class DataTableBodyComponent implements OnInit, OnDestroy { @Input() rowDefTemplate?: TemplateRef; @Input() scrollbarV: boolean; @Input() scrollbarH: boolean; @@ -221,23 +232,23 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { @Input() selectionType: SelectionType; @Input() selected: any[] = []; @Input() rowIdentity: any; - @Input() rowDetail: any; - @Input() groupHeader: any; - @Input() selectCheck: any; - @Input() displayCheck: any; + @Input() rowDetail: DatatableRowDetailDirective; + @Input() groupHeader: DatatableGroupHeaderDirective; + @Input() selectCheck: (value: TRow, index: number, array: TRow[]) => boolean; + @Input() displayCheck: (row: TRow, column: TableColumn, value?: any) => boolean; @Input() trackByProp: string; - @Input() rowClass: any; - @Input() groupedRows: any; + @Input() rowClass: (row: RowOrGroup) => string | Record; + @Input() groupedRows: Group[]; @Input() groupExpansionDefault: boolean; @Input() innerWidth: number; - @Input() groupRowsBy: string; + @Input() groupRowsBy: keyof TRow; @Input() virtualization: boolean; @Input() summaryRow: boolean; @Input() summaryPosition: string; @Input() summaryHeight: number; @Input() rowDraggable: boolean; @Input() rowDragEvents: EventEmitter; - @Input() disableRowCheck: (row: any) => boolean; + @Input() disableRowCheck: (row: TRow) => boolean; @Input() set pageSize(val: number) { if (val !== this._pageSize) { @@ -255,18 +266,18 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { return this._pageSize; } - @Input() set rows(val: any[]) { + @Input() set rows(val: TRow[]) { if (val !== this._rows) { this._rows = val; this.recalcLayout(); } } - get rows(): any[] { + get rows(): TRow[] { return this._rows; } - @Input() set columns(val: any[]) { + @Input() set columns(val: TableColumn[]) { if (val !== this._columns) { this._columns = val; this.updateColumnGroupWidths(); @@ -315,7 +326,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { @Input() @HostBinding('style.height') - set bodyHeight(val) { + set bodyHeight(val: number | string) { if (this.scrollbarV) { this._bodyHeight = val + 'px'; } else { @@ -331,13 +342,13 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { @Input() verticalScrollVisible = false; - @Output() scroll: EventEmitter = new EventEmitter(); - @Output() page: EventEmitter = new EventEmitter(); - @Output() activate: EventEmitter = new EventEmitter(); - @Output() select: EventEmitter = new EventEmitter(); + @Output() scroll: EventEmitter = new EventEmitter(); + @Output() page: EventEmitter = new EventEmitter(); + @Output() activate: EventEmitter> = new EventEmitter(); + @Output() select: EventEmitter<{selected: TRow[]}> = new EventEmitter(); @Output() detailToggle: EventEmitter = new EventEmitter(); - @Output() rowContextmenu = new EventEmitter<{ event: MouseEvent; row: any }>(false); - @Output() treeAction: EventEmitter = new EventEmitter(); + @Output() rowContextmenu = new EventEmitter<{ event: MouseEvent; row: RowOrGroup }>(false); + @Output() treeAction: EventEmitter<{row: TRow}> = new EventEmitter(); @ViewChild(ScrollerComponent) scroller: ScrollerComponent; @@ -362,25 +373,24 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { } rowHeightsCache: RowHeightCache = new RowHeightCache(); - temp: any[] = []; + temp: RowOrGroup[] = []; offsetY = 0; indexes: any = {}; - columnGroupWidths: any; - columnGroupWidthsWithoutGroup: any; - rowTrackingFn: any; + columnGroupWidths: ColumnGroupWidth; + rowTrackingFn: TrackByFunction>; listener: any; - rowIndexes: any = new WeakMap(); + rowIndexes = new WeakMap(); rowExpansions: any[] = []; - _rows: any[]; - _bodyHeight: any; - _columns: any[]; + _rows: TRow[]; + _bodyHeight: string; + _columns: TableColumn[]; _rowCount: number; _offset: number; _pageSize: number; _offsetEvent = -1; - private _draggedRow: any; + private _draggedRow: RowOrGroup; private _draggedRowElement: HTMLElement; /** @@ -388,7 +398,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { */ constructor(public cd: ChangeDetectorRef) { // declare fn here so we can get access to the `this` property - this.rowTrackingFn = (index: number, row: any): any => { + this.rowTrackingFn = (index, row) => { const idx = this.getRowIndex(row); if (this.trackByProp) { return row[this.trackByProp]; @@ -578,7 +588,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { /** * Get the row height */ - getRowHeight(row: any): number { + getRowHeight(row: RowOrGroup): number { // if its a function return it if (typeof this.rowHeight === 'function') { return this.rowHeight(row); @@ -590,7 +600,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { /** * @param group the group with all rows */ - getGroupHeight(group: any): number { + getGroupHeight(group: Group): number { let rowHeight = 0; if (group.value) { @@ -606,7 +616,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { /** * Calculate row height based on the expanded state of the row. */ - getRowAndDetailHeight(row: any): number { + getRowAndDetailHeight(row: TRow): number { let rowHeight = this.getRowHeight(row); const expanded = this.getRowExpanded(row); @@ -621,14 +631,14 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { /** * Get the height of the detail row. */ - getDetailRowHeight = (row?: any, index?: any): number => { + getDetailRowHeight = (row?: TRow, index?: number): number => { if (!this.rowDetail) { return 0; } const rowHeight = this.rowDetail.rowHeight; return typeof rowHeight === 'function' ? rowHeight(row, index) : (rowHeight as number); }; - + getGroupHeaderRowHeight = (row?: any, index?: any): number => { if (!this.groupHeader) { return 0; @@ -658,8 +668,8 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { * * @memberOf DataTableBodyComponent */ - getRowsStyles(rows: any, index = 0): any { - const styles: any = {}; + getRowsStyles(rows: RowOrGroup | TRow[], index = 0): NgStyle['ngStyle'] { + const styles: NgStyle['ngStyle'] = {}; // only add styles for the group if there is a group if (this.groupedRows) { @@ -669,7 +679,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { if (this.scrollbarV && this.virtualization) { let idx = 0; - if (this.groupedRows) { + if (Array.isArray(rows)) { // Get the latest row rowindex in a group const row = rows[rows.length - 1]; idx = row ? this.getRowIndex(row) : 0; @@ -687,7 +697,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { // until the previous row position. const pos = this.rowHeightsCache.query(idx - 1); - translateXY(styles, 0, pos); + Object.assign(styles, translateXY(0, pos)) } return styles; @@ -702,17 +712,16 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { * * @memberOf DataTableBodyComponent */ - getBottomSummaryRowStyles(): any { + getBottomSummaryRowStyles(): NgStyle['ngStyle'] { if (!this.scrollbarV || !this.rows || !this.rows.length) { return null; } - const styles = { position: 'absolute' }; const pos = this.rowHeightsCache.query(this.rows.length - 1); - - translateXY(styles, 0, pos); - - return styles; + return { + ...translateXY(0, pos), + position: 'absolute' + }; } /** @@ -734,7 +743,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { // Calculation of the first and last indexes will be based on where the // scrollY position would be at. The last index would be the one // that shows up inside the view port the last. - const height = parseInt(this.bodyHeight, 10); + const height = parseInt(this._bodyHeight, 10); first = this.rowHeightsCache.getRowIndex(this.offsetY); last = this.rowHeightsCache.getRowIndex(height + this.offsetY) + 1; } else { @@ -771,7 +780,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { // Initialize the tree only if there are rows inside the tree. if (this.rows && this.rows.length) { - const rowExpansions = new Set(); + const rowExpansions = new Set(); for (const row of this.rows) { if (this.getRowExpanded(row)) { rowExpansions.add(row); @@ -813,7 +822,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { * a part of the row object itself as we have to preserve the expanded row * status in case of sorting and filtering of the row set. */ - toggleRowExpansion(row: any): void { + toggleRowExpansion(row: TRow): void { // Capture the row index of the first row that is visible on the viewport. const viewPortFirstRowIndex = this.getAdjustedViewPortIndex(); const rowExpandedIdx = this.getRowExpandedIdx(row, this.rowExpansions); @@ -884,34 +893,10 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { return column.$$id; } - /** - * Gets the row pinning group styles - */ - stylesByGroup(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 = this.innerWidth; - const totalDiff = widths.total - bodyWidth; - const offsetDiff = totalDiff - offsetX; - const offset = offsetDiff * -1; - translateXY(styles, offset, 0); - } - - return styles; - } - /** * Returns if the row was expanded and set default row expansion when row expansion is empty */ - getRowExpanded(row: any): boolean { + getRowExpanded(row: RowOrGroup): boolean { if (this.rowExpansions.length === 0 && this.groupExpansionDefault) { for (const group of this.groupedRows) { this.rowExpansions.push(group); @@ -921,7 +906,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { return this.getRowExpandedIdx(row, this.rowExpansions) > -1; } - getRowExpandedIdx(row: any, expanded: any[]): number { + getRowExpandedIdx(row: RowOrGroup, expanded: RowOrGroup[]): number { if (!expanded || !expanded.length) {return -1;} const rowId = this.rowIdentity(row); @@ -934,15 +919,15 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { /** * Gets the row index given a row */ - getRowIndex(row: any): number { + getRowIndex(row: RowOrGroup): number { return this.rowIndexes.get(row) || 0; } - onTreeAction(row: any) { + onTreeAction(row: TRow) { this.treeAction.emit({ row }); } - dragOver(event: DragEvent, dropRow) { + dragOver(event: DragEvent, dropRow: RowOrGroup) { event.preventDefault(); this.rowDragEvents.emit({ event, @@ -953,7 +938,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { }); } - drag(event: DragEvent, dragRow, rowComponent) { + drag(event: DragEvent, dragRow: RowOrGroup, rowComponent: DataTableBodyRowComponent) { this._draggedRow = dragRow; this._draggedRowElement = rowComponent._element; this.rowDragEvents.emit({ @@ -964,7 +949,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { }); } - drop(event: DragEvent, dropRow, rowComponent) { + drop(event: DragEvent, dropRow: RowOrGroup, rowComponent: DataTableBodyRowComponent) { event.preventDefault(); this.rowDragEvents.emit({ event, @@ -976,7 +961,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { }); } - dragEnter(event: DragEvent, dropRow, rowComponent) { + dragEnter(event: DragEvent, dropRow: RowOrGroup, rowComponent: DataTableBodyRowComponent) { event.preventDefault(); this.rowDragEvents.emit({ event, @@ -988,7 +973,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { }); } - dragLeave(event: DragEvent, dropRow, rowComponent) { + dragLeave(event: DragEvent, dropRow: RowOrGroup, rowComponent: DataTableBodyRowComponent) { event.preventDefault(); this.rowDragEvents.emit({ event, @@ -1000,7 +985,7 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { }); } - dragEnd(event: DragEvent, dragRow) { + dragEnd(event: DragEvent, dragRow: RowOrGroup) { event.preventDefault(); this.rowDragEvents.emit({ event, @@ -1016,4 +1001,15 @@ export class DataTableBodyComponent implements OnInit, OnDestroy { const colsByPin = columnsByPin(this._columns); this.columnGroupWidths = columnGroupWidths(colsByPin, this._columns); } + + protected isGroup(row: RowOrGroup[]): row is Group[]; + protected isGroup(row: RowOrGroup): row is Group; + + protected isGroup(row: RowOrGroup | RowOrGroup[]): boolean { + return !!this.groupedRows; + } + + protected isRow(row: RowOrGroup): row is TRow { + return !this.groupedRows; + } } diff --git a/projects/ngx-datatable/src/lib/components/body/scroller.component.ts b/projects/ngx-datatable/src/lib/components/body/scroller.component.ts index d67f0bdf0..65d83194b 100644 --- a/projects/ngx-datatable/src/lib/components/body/scroller.component.ts +++ b/projects/ngx-datatable/src/lib/components/body/scroller.component.ts @@ -12,8 +12,6 @@ import { Renderer2 } from '@angular/core'; -import { MouseEvent } from '../../events'; - @Component({ selector: 'datatable-scroller', template: ` `, @@ -42,11 +40,10 @@ export class ScrollerComponent implements OnInit, OnDestroy { prevScrollXPos = 0; element: HTMLElement; parentElement: HTMLElement; - onScrollListener: any; private _scrollEventListener: any = null; - constructor(private ngZone: NgZone, element: ElementRef, private renderer: Renderer2) { + constructor(element: ElementRef, private renderer: Renderer2) { this.element = element.nativeElement; } diff --git a/projects/ngx-datatable/src/lib/components/body/selection.component.ts b/projects/ngx-datatable/src/lib/components/body/selection.component.ts index 133157983..93c555283 100644 --- a/projects/ngx-datatable/src/lib/components/body/selection.component.ts +++ b/projects/ngx-datatable/src/lib/components/body/selection.component.ts @@ -3,12 +3,12 @@ import { SelectionType } from '../../types/selection.type'; import { selectRows, selectRowsBetween } from '../../utils/selection'; import { Keys } from '../../utils/keys'; -export interface Model { +export interface Model { type: string; event: MouseEvent | KeyboardEvent; - row: any; - rowElement: any; - cellElement: any; + row: TRow; + rowElement: HTMLElement; + cellElement: HTMLElement; cellIndex: number; } @@ -17,31 +17,31 @@ export interface Model { template: ` `, changeDetection: ChangeDetectionStrategy.OnPush }) -export class DataTableSelectionComponent { - @Input() rows: any[]; - @Input() selected: any[]; +export class DataTableSelectionComponent { + @Input() rows: TRow[]; + @Input() selected: TRow[]; @Input() selectEnabled: boolean; @Input() selectionType: SelectionType; @Input() rowIdentity: any; - @Input() selectCheck: any; - @Input() disableCheck: any; + @Input() selectCheck: (value: TRow, index: number, array: TRow[]) => boolean; + @Input() disableCheck: (row: TRow) => boolean; - @Output() activate: EventEmitter = new EventEmitter(); - @Output() select: EventEmitter = new EventEmitter(); + @Output() activate: EventEmitter> = new EventEmitter(); + @Output() select: EventEmitter<{selected: TRow[]}> = new EventEmitter(); prevIndex: number; - selectRow(event: KeyboardEvent | MouseEvent, index: number, row: any): void { + selectRow(event: KeyboardEvent | MouseEvent, index: number, row: TRow): void { if (!this.selectEnabled) {return;} const chkbox = this.selectionType === SelectionType.checkbox; const multi = this.selectionType === SelectionType.multi; const multiClick = this.selectionType === SelectionType.multiClick; - let selected: any[] = []; + let selected: TRow[] = []; if (multi || chkbox || multiClick) { if (event.shiftKey) { - selected = selectRowsBetween([], this.rows, index, this.prevIndex, this.getRowSelectedIdx.bind(this)); + selected = selectRowsBetween([], this.rows, index, this.prevIndex); } else if ((event as KeyboardEvent).key === 'a' && (event.ctrlKey || event.metaKey)) { // select all rows except dummy rows which are added for ghostloader in case of virtual scroll selected = this.rows.filter(rowItem => !!rowItem); @@ -72,7 +72,7 @@ export class DataTableSelectionComponent { }); } - onActivate(model: Model, index: number): void { + onActivate(model: Model, index: number): void { const { type, event, row } = model; const chkbox = this.selectionType === SelectionType.checkbox; const select = (!chkbox && (type === 'click' || type === 'dblclick')) || (chkbox && type === 'checkbox'); @@ -91,7 +91,7 @@ export class DataTableSelectionComponent { this.activate.emit(model); } - onKeyboardFocus(model: Model): void { + onKeyboardFocus(model: Model): void { const { keyCode } = model.event as KeyboardEvent; const shouldFocus = keyCode === Keys.up || keyCode === Keys.down || keyCode === Keys.right || keyCode === Keys.left; @@ -111,16 +111,16 @@ export class DataTableSelectionComponent { } } - focusRow(rowElement: any, keyCode: number): void { + focusRow(rowElement: HTMLElement, keyCode: number): void { const nextRowElement = this.getPrevNextRow(rowElement, keyCode); if (nextRowElement) {nextRowElement.focus();} } - getPrevNextRow(rowElement: any, keyCode: number): any { + getPrevNextRow(rowElement: HTMLElement, keyCode: number): any { const parentElement = rowElement.parentElement; if (parentElement) { - let focusElement: HTMLElement; + let focusElement: Element; if (keyCode === Keys.up) { focusElement = parentElement.previousElementSibling; } else if (keyCode === Keys.down) { @@ -133,8 +133,8 @@ export class DataTableSelectionComponent { } } - focusCell(cellElement: any, rowElement: any, keyCode: number, cellIndex: number): void { - let nextCellElement: HTMLElement; + focusCell(cellElement: HTMLElement, rowElement: HTMLElement, keyCode: number, cellIndex: number): void { + let nextCellElement: Element; if (keyCode === Keys.left) { nextCellElement = cellElement.previousElementSibling; @@ -148,14 +148,14 @@ export class DataTableSelectionComponent { } } - if (nextCellElement) {nextCellElement.focus();} + if (nextCellElement && 'focus' in nextCellElement && typeof nextCellElement.focus === 'function') {nextCellElement.focus();} } - getRowSelected(row: any): boolean { + getRowSelected(row: TRow): boolean { return this.getRowSelectedIdx(row, this.selected) > -1; } - getRowSelectedIdx(row: any, selected: any[]): number { + getRowSelectedIdx(row: TRow, selected: any[]): number { if (!selected || !selected.length) {return -1;} const rowId = this.rowIdentity(row); diff --git a/projects/ngx-datatable/src/lib/components/body/summary/summary-row.component.ts b/projects/ngx-datatable/src/lib/components/body/summary/summary-row.component.ts index 83c1a29d8..10fc98093 100644 --- a/projects/ngx-datatable/src/lib/components/body/summary/summary-row.component.ts +++ b/projects/ngx-datatable/src/lib/components/body/summary/summary-row.component.ts @@ -1,10 +1,11 @@ import { Component, Input, OnChanges, PipeTransform, TemplateRef } from '@angular/core'; +import { TableColumn, TableColumnProp } from '../../../types/table-column.type'; export interface ISummaryColumn { summaryFunc?: (cells: any[]) => any; summaryTemplate?: TemplateRef; - prop: string; + prop?: TableColumnProp; pipe?: PipeTransform; } @@ -46,7 +47,7 @@ function noopSumFunc(cells: any[]): void { }) export class DataTableSummaryRowComponent implements OnChanges { @Input() rows: any[]; - @Input() columns: ISummaryColumn[]; + @Input() columns: TableColumn[]; @Input() rowHeight: number; @Input() offsetX: number; diff --git a/projects/ngx-datatable/src/lib/components/columns/column-ghost-cell.directive.ts b/projects/ngx-datatable/src/lib/components/columns/column-ghost-cell.directive.ts index b8e5a3aca..fcb388ca3 100644 --- a/projects/ngx-datatable/src/lib/components/columns/column-ghost-cell.directive.ts +++ b/projects/ngx-datatable/src/lib/components/columns/column-ghost-cell.directive.ts @@ -2,5 +2,10 @@ import { Directive, TemplateRef } from '@angular/core'; @Directive({ selector: '[ngx-datatable-ghost-cell-template]' }) export class DataTableColumnGhostCellDirective { - constructor(public template: TemplateRef) {} + static ngTemplateContextGuard( + directive: DataTableColumnGhostCellDirective, + context: unknown + ): context is void { + return true; + } } diff --git a/projects/ngx-datatable/src/lib/components/columns/column-header.directive.ts b/projects/ngx-datatable/src/lib/components/columns/column-header.directive.ts index 5c2b19739..b4e470000 100644 --- a/projects/ngx-datatable/src/lib/components/columns/column-header.directive.ts +++ b/projects/ngx-datatable/src/lib/components/columns/column-header.directive.ts @@ -1,6 +1,12 @@ -import { Directive, TemplateRef } from '@angular/core'; +import { Directive } from '@angular/core'; +import { HeaderCellContext } from '../../types/cell-context.type'; @Directive({ selector: '[ngx-datatable-header-template]' }) export class DataTableColumnHeaderDirective { - constructor(public template: TemplateRef) {} + static ngTemplateContextGuard( + directive: DataTableColumnHeaderDirective, + context: unknown + ): context is HeaderCellContext { + return true; + } } diff --git a/projects/ngx-datatable/src/lib/components/columns/column.directive.ts b/projects/ngx-datatable/src/lib/components/columns/column.directive.ts index bef9c165f..3f66fb4d3 100644 --- a/projects/ngx-datatable/src/lib/components/columns/column.directive.ts +++ b/projects/ngx-datatable/src/lib/components/columns/column.directive.ts @@ -5,6 +5,7 @@ import { DataTableColumnCellTreeToggle } from './tree.directive'; import { ColumnChangesService } from '../../services/column-changes.service'; import { TableColumnProp } from '../../types/table-column.type'; import { DataTableColumnGhostCellDirective } from './column-ghost-cell.directive'; +import { HeaderCellContext } from '../../types/cell-context.type'; @Directive({ selector: 'ngx-datatable-column' }) export class DataTableColumnDirective implements OnChanges { @@ -42,12 +43,12 @@ export class DataTableColumnDirective implements OnChanges { } @Input('headerTemplate') - _headerTemplateInput: TemplateRef; + _headerTemplateInput: TemplateRef; @ContentChild(DataTableColumnHeaderDirective, { read: TemplateRef, static: true }) - _headerTemplateQuery: TemplateRef; + _headerTemplateQuery: TemplateRef; - get headerTemplate(): TemplateRef { + get headerTemplate(): TemplateRef { return this._headerTemplateInput || this._headerTemplateQuery; } @@ -62,12 +63,12 @@ export class DataTableColumnDirective implements OnChanges { } @Input('ghostCellTemplate') - _ghostCellTemplateInput: TemplateRef; + _ghostCellTemplateInput: TemplateRef; @ContentChild(DataTableColumnGhostCellDirective, { read: TemplateRef, static: true }) - _ghostCellTemplateQuery: TemplateRef; + _ghostCellTemplateQuery: TemplateRef; - get ghostCellTemplate(): TemplateRef { + get ghostCellTemplate(): TemplateRef { return this._ghostCellTemplateInput || this._ghostCellTemplateQuery; } diff --git a/projects/ngx-datatable/src/lib/components/datatable.component.html b/projects/ngx-datatable/src/lib/components/datatable.component.html index 48792d328..adc4cf261 100644 --- a/projects/ngx-datatable/src/lib/components/datatable.component.html +++ b/projects/ngx-datatable/src/lib/components/datatable.component.html @@ -24,7 +24,7 @@ (resize)="onColumnResize($event)" (resizing)="onColumnResizing($event)" (reorder)="onColumnReorder($event)" - (select)="onHeaderSelect($event)" + (select)="onHeaderSelect()" (columnContextmenu)="onColumnContextmenu($event)" > diff --git a/projects/ngx-datatable/src/lib/components/datatable.component.ts b/projects/ngx-datatable/src/lib/components/datatable.component.ts index 02e410293..67fb5bbfe 100644 --- a/projects/ngx-datatable/src/lib/components/datatable.component.ts +++ b/projects/ngx-datatable/src/lib/components/datatable.component.ts @@ -13,8 +13,8 @@ import { HostListener, Inject, Input, - KeyValueDiffer, - KeyValueDiffers, + IterableDiffer, + IterableDiffers, OnDestroy, OnInit, Optional, @@ -48,9 +48,19 @@ import { ColumnChangesService } from '../services/column-changes.service'; import { DimensionsHelper } from '../services/dimensions-helper.service'; import { throttleable } from '../utils/throttle'; import { adjustColumnWidths, forceFillColumnWidths } from '../utils/math'; +import { Group, RowOrGroup } from '../types/group.type'; +import { SortPropDir } from '../types/sort-prop-dir.type'; +import { NgClass } from '@angular/common'; +import { Model } from './body/selection.component'; +import { SortEvent } from '../types/sort-direction.type'; +import { BodyPageEvent, PageEvent, PagerPageEvent } from '../types/page-event.type'; +import { ReorderEvent } from '../types/orderable.types'; +import { ColumnResizeEvent } from '../types/resize.type'; import { sortGroupedRows, sortRows } from '../utils/sort'; import { DatatableRowDefDirective } from './body/body-row-def.component'; import { DatatableComponentToken } from '../utils/table-token'; +import { ScrollEvent } from '../types/scroll.type'; +import { TreeStatus } from './body/body-cell.component'; @Component({ selector: 'ngx-datatable', @@ -67,16 +77,16 @@ import { DatatableComponentToken } from '../utils/table-token'; useExisting: DatatableComponent }] }) -export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, AfterContentInit, OnDestroy { +export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, AfterContentInit, OnDestroy { /** * Template for the target marker of drag target columns. */ - @Input() targetMarkerTemplate: any; + @Input() targetMarkerTemplate: TemplateRef; /** * Rows that are displayed in the table. */ - @Input() set rows(val: any) { + @Input() set rows(val: TRow[] | null | undefined) { this._rows = val; if (val) { @@ -109,18 +119,18 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * Gets the rows. */ - get rows(): any { + get rows(): TRow[] { return this._rows; } /** * This attribute allows the user to set the name of the column to group the data with */ - @Input() set groupRowsBy(val: string) { + @Input() set groupRowsBy(val: keyof TRow) { if (val) { this._groupRowsBy = val; if (this._rows && this._groupRowsBy) { - // cretes a new array with the data grouped + // creates a new array with the data grouped this.groupedRows = this.groupArrayBy(this._rows, this._groupRowsBy); } } @@ -145,7 +155,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * ]} * ] */ - @Input() groupedRows: any[]; + @Input() groupedRows: Group[]; /** * Columns to be displayed. @@ -172,7 +182,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * represented as selected in the grid. * Default value: `[]` */ - @Input() selected: any[] = []; + @Input() selected: TRow[] = []; /** * Enable vertical scrollbars @@ -196,7 +206,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * The row height; which is necessary * to calculate the height for the lazy rendering. */ - @Input() rowHeight: number | 'auto' | ((row?: any) => number) = 30; + @Input() rowHeight: number | 'auto' | ((row?: TRow) => number) = 30; /** * Type of column width distribution formula. @@ -331,12 +341,12 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * Array of sorted columns by property and type. * Default value: `[]` */ - @Input() sorts: any[] = []; + @Input() sorts: SortPropDir[] = []; /** * Css class overrides */ - @Input() cssClasses: any = { + @Input() cssClasses: INgxDatatableConfig['cssClasses'] = { sortAscending: 'datatable-icon-up', sortDescending: 'datatable-icon-down', sortUnset: 'datatable-icon-sort-unset', @@ -353,7 +363,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * totalMessage [default] = 'total' * selectedMessage [default] = 'selected' */ - @Input() messages: any = { + @Input() messages: INgxDatatableConfig['messages'] = { // Message to show when array is presented // but contains no values emptyMessage: 'No data to display', @@ -366,13 +376,11 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After }; /** - * Row specific classes. - * Similar implementation to ngClass. - * - * [rowClass]="'first second'" - * [rowClass]="{ 'first': true, 'second': true, 'third': false }" + * A function which is called with the row and should return either: + * - a string: `"class-1 class-2` + * - a Record: `{ 'class-1': true, 'class-2': false }` */ - @Input() rowClass: any; + @Input() rowClass: (row: Group | TRow) => string | Record; /** * A boolean/function you can use to check whether you want @@ -382,7 +390,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * return selection !== 'Ethel Price'; * } */ - @Input() selectCheck: any; + @Input() selectCheck: (value: TRow, index: number, array: TRow[]) => boolean; /** * A function you can use to check whether you want @@ -392,7 +400,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * return row.name !== 'Ethel Price'; * } */ - @Input() displayCheck: (row: any, column?: any, value?: any) => boolean; + @Input() displayCheck: (row: TRow, column: TableColumn, value?: any) => boolean; /** * A boolean you can use to set the detault behaviour of rows and groups @@ -453,7 +461,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * return row.name !== 'Ethel Price'; * } */ - @Input() disableRowCheck: (row: any) => boolean; + @Input() disableRowCheck: (row: TRow) => boolean; /** * A flag to enable drag behavior of native HTML5 drag and drop API on rows. @@ -471,49 +479,49 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * Body was scrolled typically in a `scrollbarV:true` scenario. */ - @Output() scroll: EventEmitter = new EventEmitter(); + @Output() scroll: EventEmitter = new EventEmitter(); /** * A cell or row was focused via keyboard or mouse click. */ - @Output() activate: EventEmitter = new EventEmitter(); + @Output() activate: EventEmitter> = new EventEmitter(); /** * A cell or row was selected. */ - @Output() select: EventEmitter = new EventEmitter(); + @Output() select: EventEmitter<{selected: TRow[]}> = new EventEmitter(); /** * Column sort was invoked. */ - @Output() sort: EventEmitter = new EventEmitter(); + @Output() sort: EventEmitter = new EventEmitter(); /** * The table was paged either triggered by the pager or the body scroll. */ - @Output() page: EventEmitter = new EventEmitter(); + @Output() page: EventEmitter = new EventEmitter(); /** * Columns were re-ordered. */ - @Output() reorder: EventEmitter = new EventEmitter(); + @Output() reorder: EventEmitter = new EventEmitter(); /** * Column was resized. */ - @Output() resize: EventEmitter = new EventEmitter(); + @Output() resize: EventEmitter = new EventEmitter(); /** * The context menu was invoked on the table. * type indicates whether the header or the body was clicked. * content contains either the column or the row that was clicked. */ - @Output() tableContextmenu = new EventEmitter<{ event: MouseEvent; type: ContextmenuType; content: any }>(false); + @Output() tableContextmenu = new EventEmitter<{ event: MouseEvent; type: ContextmenuType; content: TableColumn | RowOrGroup }>(false); /** * A row was expanded ot collapsed for tree */ - @Output() treeAction: EventEmitter = new EventEmitter(); + @Output() treeAction: EventEmitter<{row: TRow; rowIndex: number}> = new EventEmitter(); /** * Emits HTML5 native drag events. @@ -655,7 +663,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * invoking functions on the body. */ @ViewChild(DataTableBodyComponent) - bodyComponent: DataTableBodyComponent; + bodyComponent: DataTableBodyComponent; /** * Reference to the header component for manually @@ -692,15 +700,15 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After pageSize: number; bodyHeight: number; rowCount = 0; - rowDiffer: KeyValueDiffer; + rowDiffer: IterableDiffer; _offsetX = new BehaviorSubject(0); _limit: number | undefined; _count = 0; _offset = 0; - _rows: any[]; - _groupRowsBy: string; - _internalRows: any[]; + _rows: TRow[] | null | undefined; + _groupRowsBy: keyof TRow; + _internalRows: TRow[]; _internalColumns: TableColumn[]; _columns: TableColumn[]; _columnTemplates: QueryList; @@ -712,14 +720,14 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After @SkipSelf() private scrollbarHelper: ScrollbarHelper, @SkipSelf() private dimensionsHelper: DimensionsHelper, private cd: ChangeDetectorRef, - element: ElementRef, - differs: KeyValueDiffers, + element: ElementRef, + differs: IterableDiffers, private columnChangesService: ColumnChangesService, @Optional() @Inject('configuration') private configuration: INgxDatatableConfig ) { // get ref to elm for measuring this.element = element.nativeElement; - this.rowDiffer = differs.find({}).create(); + this.rowDiffer = differs.find([]).create(); // apply global settings from Module.forRoot if (this.configuration) { @@ -791,11 +799,11 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * * (`fn(x) === fn(y)` instead of `x === y`) */ - @Input() rowIdentity: (x: any) => any = (x: any) => { + @Input() rowIdentity: (x: TRow | Group) => unknown = x => { if (this._groupRowsBy) { // each group in groupedRows are stored as {key, value: [rows]}, // where key is the groupRowsBy index - return x.key ?? x; + return (x as Group).key ?? x; } else { return x; } @@ -804,7 +812,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * Translates the templates to the column objects */ - translateColumns(val: any) { + translateColumns(val: QueryList) { if (val) { const arr = val.toArray(); if (arr.length) { @@ -823,14 +831,14 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * Creates a map with the data grouped by the user choice of grouping index * * @param originalArray the original array passed via parameter - * @param groupBy the index of the column to group the data by + * @param groupBy the key of the column to group the data by */ - groupArrayBy(originalArray: any, groupBy: any) { + groupArrayBy(originalArray: TRow[], groupBy: keyof TRow) { // create a map to hold groups with their corresponding results - const map = new Map(); + const map = new Map(); let i = 0; - originalArray.forEach((item: any) => { + originalArray.forEach(item => { const key = item[groupBy]; if (!map.has(key)) { map.set(key, [item]); @@ -840,7 +848,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After i++; }); - const addGroup = (key: any, value: any) => ({ key, value }); + const addGroup = (key: TRow[keyof TRow], value: TRow[]) => ({ key, value }); // convert map back to a simple array of objects return Array.from(map, x => addGroup(x[0], x[1])); @@ -908,10 +916,10 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After * distribution mode and scrollbar offsets. */ recalculateColumns( - columns: any[] = this._internalColumns, + columns: TableColumn[] = this._internalColumns, forceIdx: number = -1, allowBleed: boolean = this.scrollbarH - ): any[] | undefined { + ): TableColumn[] | undefined { if (!columns) {return undefined;} let width = this._innerWidth; @@ -923,7 +931,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After const scrollerHeight = this.bodyComponent?.scroller?.element.offsetHeight; if (scrollerHeight && this.bodyHeight < scrollerHeight) { width = width - (this.verticalScrollVisible ? this.scrollbarHelper.width : 0); - } + } if (this.headerComponent && this.headerComponent.innerWidth !== width){ this.headerComponent.innerWidth = width; @@ -978,7 +986,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * Body triggered a page event. */ - onBodyPage({ offset }: any): void { + onBodyPage({ offset }: BodyPageEvent): void { // Avoid pagination caming from body events like scroll when the table // has no virtualization and the external paging is enable. // This means, let's the developer handle pagination by my him(her) self @@ -1001,7 +1009,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * The body triggered a scroll event. */ - onBodyScroll(event: MouseEvent): void { + onBodyScroll(event: ScrollEvent): void { this._offsetX.next(event.offsetX); this.scroll.emit(event); this.cd.detectChanges(); @@ -1010,7 +1018,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * The footer triggered a page event. */ - onFooterPage(event: any) { + onFooterPage(event: PagerPageEvent) { this.offset = event.page - 1; this.bodyComponent.updateOffsetY(this.offset); @@ -1032,7 +1040,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * Recalculates the sizes of the page */ - calcPageSize(val: any[] = this.rows): number { + calcPageSize(): number { // Keep the page size constant even if the row has been expanded. // This is because an expanded row is still considered to be a child of // the original row. Hence calculation would use rowHeight only. @@ -1047,8 +1055,8 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After } // otherwise use row length - if (val) { - return val.length; + if (this.rows) { + return this.rows.length; } // other empty :( @@ -1058,16 +1066,16 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * Calculates the row count. */ - calcRowCount(val: any[] = this.rows): number { + calcRowCount(): number { if (!this.externalPaging) { - if (!val) {return 0;} + if (!this.rows) {return 0;} if (this.groupedRows) { return this.groupedRows.length; } else if (this.treeFromRelation != null && this.treeToRelation != null) { return this._internalRows.length; } else { - return val.length; + return this.rows.length; } } @@ -1077,21 +1085,21 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * The header triggered a contextmenu event. */ - onColumnContextmenu({ event, column }: any): void { + onColumnContextmenu({ event, column }: {event: MouseEvent; column: TableColumn}): void { this.tableContextmenu.emit({ event, type: ContextmenuType.header, content: column }); } /** * The body triggered a contextmenu event. */ - onRowContextmenu({ event, row }: any): void { + onRowContextmenu({ event, row }: {event: MouseEvent; row: RowOrGroup}): void { this.tableContextmenu.emit({ event, type: ContextmenuType.body, content: row }); } /** * The header triggered a column resize event. */ - onColumnResize({ column, newValue }: any): void { + onColumnResize({ column, newValue, prevValue }: ColumnResizeEvent): void { /* Safari/iOS 10.2 workaround */ if (column === undefined) { return; @@ -1118,11 +1126,12 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After this.resize.emit({ column, - newValue + newValue, + prevValue }); } - onColumnResizing({ column, newValue }: any): void { + onColumnResizing({ column, newValue }: ColumnResizeEvent): void { if (column === undefined) { return; } @@ -1135,7 +1144,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * The header triggered a column re-order event. */ - onColumnReorder({ column, newValue, prevValue }: any): void { + onColumnReorder({ column, newValue, prevValue }: ReorderEvent): void { const cols = this._internalColumns.map(c => ({ ...c })); if (this.swapColumns) { @@ -1170,7 +1179,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * The header triggered a column sort event. */ - onColumnSort(event: any): void { + onColumnSort(event: SortEvent): void { // clean selected rows if (this.selectAllRowsOnPage) { this.selected = []; @@ -1211,7 +1220,7 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * Toggle all row selection */ - onHeaderSelect(event: any): void { + onHeaderSelect(): void { if (this.bodyComponent && this.selectAllRowsOnPage) { // before we splice, chk if we currently have all selected const first = this.bodyComponent.indexes.first; @@ -1250,14 +1259,14 @@ export class DatatableComponent implements OnInit, DoCheck, AfterViewInit, After /** * A row was selected from body */ - onBodySelect(event: any): void { + onBodySelect(event: {selected: TRow[]}): void { this.select.emit(event); } /** * A row was expanded or collapsed for tree */ - onTreeAction(event: any) { + onTreeAction(event: {row: TRow}) { const row = event.row; // TODO: For duplicated items this will not work const rowIndex = this._rows.findIndex(r => r[this.treeToRelation] === event.row[this.treeToRelation]); diff --git a/projects/ngx-datatable/src/lib/components/footer/footer-template.directive.ts b/projects/ngx-datatable/src/lib/components/footer/footer-template.directive.ts index 6ed41f817..3dec0cbc3 100644 --- a/projects/ngx-datatable/src/lib/components/footer/footer-template.directive.ts +++ b/projects/ngx-datatable/src/lib/components/footer/footer-template.directive.ts @@ -1,6 +1,12 @@ -import { Directive, TemplateRef } from '@angular/core'; +import { Directive } from '@angular/core'; +import { FooterContext } from '../../types/footer-context'; @Directive({ selector: '[ngx-datatable-footer-template]' }) export class DataTableFooterTemplateDirective { - constructor(public template: TemplateRef) {} + static ngTemplateContextGuard( + directive: DataTableFooterTemplateDirective, + context: unknown + ): context is FooterContext { + return true; + } } diff --git a/projects/ngx-datatable/src/lib/components/footer/footer.component.ts b/projects/ngx-datatable/src/lib/components/footer/footer.component.ts index 7d0f94790..46546c618 100644 --- a/projects/ngx-datatable/src/lib/components/footer/footer.component.ts +++ b/projects/ngx-datatable/src/lib/components/footer/footer.component.ts @@ -1,5 +1,6 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; import { DatatableFooterDirective } from './footer.directive'; +import { PagerPageEvent } from '../../types/page-event.type'; @Component({ selector: 'datatable-footer', template: ` @@ -59,7 +60,7 @@ export class DataTableFooterComponent { @Input() selectedCount = 0; @Input() selectedMessage: string | boolean; - @Output() page: EventEmitter = new EventEmitter(); + @Output() page: EventEmitter = new EventEmitter(); get isVisible(): boolean { return this.rowCount / this.pageSize > 1; diff --git a/projects/ngx-datatable/src/lib/components/footer/footer.directive.ts b/projects/ngx-datatable/src/lib/components/footer/footer.directive.ts index 9f965988e..1d3488cc7 100644 --- a/projects/ngx-datatable/src/lib/components/footer/footer.directive.ts +++ b/projects/ngx-datatable/src/lib/components/footer/footer.directive.ts @@ -1,5 +1,6 @@ import { ContentChild, Directive, Input, TemplateRef } from '@angular/core'; import { DataTableFooterTemplateDirective } from './footer-template.directive'; +import { FooterContext } from '../../types/footer-context'; @Directive({ selector: 'ngx-datatable-footer' }) export class DatatableFooterDirective { @@ -12,12 +13,12 @@ export class DatatableFooterDirective { @Input() pagerNextIcon: string; @Input('template') - _templateInput: TemplateRef; + _templateInput: TemplateRef; @ContentChild(DataTableFooterTemplateDirective, { read: TemplateRef }) - _templateQuery: TemplateRef; + _templateQuery: TemplateRef; - get template(): TemplateRef { + get template(): TemplateRef { return this._templateInput || this._templateQuery; } } diff --git a/projects/ngx-datatable/src/lib/components/footer/pager.component.ts b/projects/ngx-datatable/src/lib/components/footer/pager.component.ts index 3e35db47d..787f44d3c 100644 --- a/projects/ngx-datatable/src/lib/components/footer/pager.component.ts +++ b/projects/ngx-datatable/src/lib/components/footer/pager.component.ts @@ -1,4 +1,6 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; +import { PagerPageEvent } from '../../types/page-event.type'; +import { Page } from '../../types/pages.type'; @Component({ selector: 'datatable-pager', @@ -83,12 +85,12 @@ export class DataTablePagerComponent { return Math.max(count || 0, 1); } - @Output() change: EventEmitter = new EventEmitter(); + @Output() change: EventEmitter = new EventEmitter(); _count = 0; _page = 1; _size = 0; - pages: any; + pages: Page[]; canPrevious(): boolean { return this.page > 1; @@ -116,8 +118,8 @@ export class DataTablePagerComponent { } } - calcPages(page?: number): any[] { - const pages = []; + calcPages(page?: number): Page[] { + const pages: Page[] = []; let startPage = 1; let endPage = this.totalPages; const maxSize = 5; diff --git a/projects/ngx-datatable/src/lib/components/header/header-cell.component.ts b/projects/ngx-datatable/src/lib/components/header/header-cell.component.ts index 4d5087f33..d0bd8013a 100644 --- a/projects/ngx-datatable/src/lib/components/header/header-cell.component.ts +++ b/projects/ngx-datatable/src/lib/components/header/header-cell.component.ts @@ -7,13 +7,15 @@ import { HostListener, Input, OnInit, - Output + Output, TemplateRef } from '@angular/core'; import { SortType } from '../../types/sort.type'; import { SelectionType } from '../../types/selection.type'; import { TableColumn } from '../../types/table-column.type'; import { nextSortDir } from '../../utils/sort'; -import { SortDirection } from '../../types/sort-direction.type'; +import { InnerSortEvent, SortDirection } from '../../types/sort-direction.type'; +import { SortPropDir } from '../../types/sort-prop-dir.type'; +import { HeaderCellContext } from '../../types/cell-context.type'; @Component({ selector: 'datatable-header-cell', @@ -26,7 +28,7 @@ import { SortDirection } from '../../types/sort-direction.type'; >
@@ -52,7 +54,7 @@ export class DataTableHeaderCellComponent implements OnInit { @Input() sortUnsetIcon: string; @Input() isTarget: boolean; - @Input() targetMarkerTemplate: any; + @Input() targetMarkerTemplate: TemplateRef; @Input() targetMarkerContext: any; @Input() enableClearingSortState = false; @@ -82,7 +84,7 @@ export class DataTableHeaderCellComponent implements OnInit { @Input() headerHeight: number; - @Input() set sorts(val: any[]) { + @Input() set sorts(val: SortPropDir[]) { this._sorts = val; this.sortDir = this.calcSortDir(val); this.cellContext.sortDir = this.sortDir; @@ -90,16 +92,16 @@ export class DataTableHeaderCellComponent implements OnInit { this.cd.markForCheck(); } - get sorts(): any[] { + get sorts(): SortPropDir[] { return this._sorts; } - @Output() sort: EventEmitter = new EventEmitter(); - @Output() select: EventEmitter = new EventEmitter(); - @Output() columnContextmenu = new EventEmitter<{ event: MouseEvent; column: any }>(false); + @Output() sort: EventEmitter = new EventEmitter(); + @Output() select: EventEmitter = new EventEmitter(); + @Output() columnContextmenu = new EventEmitter<{ event: MouseEvent; column: TableColumn }>(false); @HostBinding('class') - get columnCssClasses(): any { + get columnCssClasses(): string { let cls = 'datatable-header-cell'; if (this.column.sortable) {cls += ' sortable';} @@ -160,23 +162,21 @@ export class DataTableHeaderCellComponent implements OnInit { return this.column.headerCheckboxable; } - sortFn = this.onSort.bind(this); sortClass: string; sortDir: SortDirection; - selectFn = this.select.emit.bind(this.select); - cellContext: any; + cellContext: HeaderCellContext; private _column: TableColumn; - private _sorts: any[]; + private _sorts: SortPropDir[]; constructor(private cd: ChangeDetectorRef) { this.cellContext = { column: this.column, sortDir: this.sortDir, - sortFn: this.sortFn, + sortFn: () => this.onSort(), allRowsSelected: this.allRowsSelected, - selectFn: this.selectFn + selectFn: () => this.select.emit() }; } @@ -198,7 +198,7 @@ export class DataTableHeaderCellComponent implements OnInit { } } - calcSortDir(sorts: any[]): any { + calcSortDir(sorts: SortPropDir[]): any { if (sorts && this.column) { const sort = sorts.find((s: any) => s.prop === this.column.prop); diff --git a/projects/ngx-datatable/src/lib/components/header/header.component.ts b/projects/ngx-datatable/src/lib/components/header/header.component.ts index 8bb66d30e..54287eac5 100644 --- a/projects/ngx-datatable/src/lib/components/header/header.component.ts +++ b/projects/ngx-datatable/src/lib/components/header/header.component.ts @@ -9,14 +9,21 @@ import { OnDestroy, Output, SimpleChanges, - SkipSelf + SkipSelf, + TemplateRef } from '@angular/core'; import { columnGroupWidths, columnsByPin, columnsByPinArr } from '../../utils/column'; import { SortType } from '../../types/sort.type'; import { SelectionType } from '../../types/selection.type'; -import { DataTableColumnDirective } from '../columns/column.directive'; import { translateXY } from '../../utils/translate'; +import { NgStyle } from '@angular/common'; import { ScrollbarHelper } from '../../services/scrollbar-helper.service'; +import { TableColumn } from '../../types/table-column.type'; +import { PinnedColumns } from '../../types/column-pin.type'; +import { InnerSortEvent, SortDirection, SortEvent } from '../../types/sort-direction.type'; +import { SortPropDir } from '../../types/sort-prop-dir.type'; +import { OrderableReorderEvent, ReorderEvent, TargetChangedEvent } from '../../types/orderable.types'; +import { ColumnResizeEvent } from '../../types/resize.type'; @Component({ selector: 'datatable-header', @@ -78,16 +85,14 @@ import { ScrollbarHelper } from '../../services/scrollbar-helper.service'; changeDetection: ChangeDetectionStrategy.OnPush }) export class DataTableHeaderComponent implements OnDestroy, OnChanges { - @Input() sortAscendingIcon: any; - @Input() sortDescendingIcon: any; - @Input() sortUnsetIcon: any; + @Input() sortAscendingIcon: string; + @Input() sortDescendingIcon: string; + @Input() sortUnsetIcon: string; @Input() scrollbarH: boolean; @Input() dealsWithGroup: boolean; - @Input() targetMarkerTemplate: any; + @Input() targetMarkerTemplate: TemplateRef; @Input() enableClearingSortState = false; - targetMarkerContext: any; - @Input() set innerWidth(val: number) { this._innerWidth = val; setTimeout(() => { @@ -103,14 +108,14 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { return this._innerWidth; } - @Input() sorts: any[]; + @Input() sorts: SortPropDir[]; @Input() sortType: SortType; @Input() allRowsSelected: boolean; @Input() selectionType: SelectionType; @Input() reorderable: boolean; @Input() verticalScrollVisible = false; - dragEventTarget: any; + dragEventTarget?: MouseEvent; @HostBinding('style.height') @Input() @@ -126,7 +131,7 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { return this._headerHeight; } - @Input() set columns(val: any[]) { + @Input() set columns(val: TableColumn[]) { this._columns = val; const colsByPin = columnsByPin(val); @@ -150,26 +155,26 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { return this._offsetX; } - @Output() sort: EventEmitter = new EventEmitter(); - @Output() reorder: EventEmitter = new EventEmitter(); - @Output() resize: EventEmitter = new EventEmitter(); - @Output() resizing: EventEmitter = new EventEmitter(); - @Output() select: EventEmitter = new EventEmitter(); - @Output() columnContextmenu = new EventEmitter<{ event: MouseEvent; column: any }>(false); + @Output() sort: EventEmitter = new EventEmitter(); + @Output() reorder: EventEmitter = new EventEmitter(); + @Output() resize: EventEmitter = new EventEmitter(); + @Output() resizing: EventEmitter = new EventEmitter(); + @Output() select: EventEmitter = new EventEmitter(); + @Output() columnContextmenu = new EventEmitter<{ event: MouseEvent; column: TableColumn }>(false); - _columnsByPin: any; + _columnsByPin: PinnedColumns[]; _columnGroupWidths: any = { total: 100 }; _innerWidth: number; _offsetX: number; - _columns: any[]; + _columns: TableColumn[]; _headerHeight: string; - _styleByGroup: { [prop: string]: unknown } = { - left: {}, - center: {}, - right: {} - }; + _styleByGroup: { + left: NgStyle['ngStyle'], + center: NgStyle['ngStyle'], + right: NgStyle['ngStyle'] + } = { left: {}, center: {}, right: {} }; private destroyed = false; @@ -188,13 +193,13 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { this.destroyed = true; } - onLongPressStart({ event, model }: { event: any; model: any }) { + onLongPressStart({ event, model }: { event: MouseEvent; model: TableColumn }) { model.dragging = true; this.dragEventTarget = event; } - onLongPressEnd({ event, model }: { event: any; model: any }) { - this.dragEventTarget = event; + onLongPressEnd({ model }: { model: TableColumn }) { + this.dragEventTarget = undefined; // delay resetting so sort can be // prevented if we were dragging @@ -202,7 +207,7 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { // datatable component creates copies from columns on reorder // set dragging to false on new objects const column = this._columns.find(c => c.$$id === model.$$id); - if (column) { + if (column && 'dragging' in column) { column.dragging = false; } }, 5); @@ -218,23 +223,23 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { return '100%'; } - trackByGroups(index: number, colGroup: any): any { + trackByGroups(index: number, colGroup: PinnedColumns): string { return colGroup.type; } - columnTrackingFn(index: number, column: any): any { + columnTrackingFn(index: number, column: TableColumn): string { return column.$$id; } - onColumnResized(width: number, column: DataTableColumnDirective): void { + onColumnResized(width: number, column: TableColumn): void { this.resize.emit(this.makeResizeEvent(width, column)); } - onColumnResizing(width: number, column: DataTableColumnDirective): void { + onColumnResizing(width: number, column: TableColumn): void { this.resizing.emit(this.makeResizeEvent(width, column)); } - private makeResizeEvent(width: number, column: DataTableColumnDirective) { + private makeResizeEvent(width: number, column: TableColumn): ColumnResizeEvent { if (width <= column.minWidth) { width = column.minWidth; } else if (width >= column.maxWidth) { @@ -247,7 +252,7 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { }; } - onColumnReordered({ prevIndex, newIndex, model }: any): void { + onColumnReordered({ prevIndex, newIndex, model }: OrderableReorderEvent): void { const column = this.getColumn(newIndex); column.isTarget = false; column.targetMarkerContext = undefined; @@ -258,7 +263,7 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { }); } - onTargetChanged({ prevIndex, newIndex, initialIndex }: any): void { + onTargetChanged({ prevIndex, newIndex, initialIndex }: TargetChangedEvent): void { if (prevIndex || prevIndex === 0) { const oldColumn = this.getColumn(prevIndex); oldColumn.isTarget = false; @@ -290,7 +295,7 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { return this._columnsByPin[2].columns[index - leftColumnCount - centerColumnCount]; } - onSort({ column, prevValue, newValue }: any): void { + onSort({ column, prevValue, newValue }: InnerSortEvent): void { // if we are dragging don't sort! if (column.dragging) { return; @@ -305,7 +310,7 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { }); } - calcNewSorts(column: any, prevValue: number, newValue: number): any[] { + calcNewSorts(column: TableColumn, prevValue: SortDirection, newValue: SortDirection): SortPropDir[] { let idx = 0; if (!this.sorts) { @@ -344,22 +349,27 @@ export class DataTableHeaderComponent implements OnDestroy, OnChanges { } } - calcStylesByGroup(group: string): any { + calcStylesByGroup(group: 'center' | 'right' | 'left'): NgStyle['ngStyle'] { const widths = this._columnGroupWidths; const offsetX = this.offsetX; - const styles = { - width: `${widths[group]}px` - }; - if (group === 'center') { - translateXY(styles, offsetX * -1, 0); + return { + ...translateXY(offsetX * -1, 0), + width: `${widths[group]}px` + } } else if (group === 'right') { const totalDiff = widths.total - this.innerWidth; const offset = (totalDiff + (this.verticalScrollVisible ? this.scrollbarHelper.width : 0)) * -1; - translateXY(styles, offset, 0); + return { + ...translateXY(offset, 0), + width: `${widths[group]}px` + + } } - return styles; + return { + width: `${widths[group]}px` + }; } } diff --git a/projects/ngx-datatable/src/lib/components/row-detail/row-detail-template.directive.ts b/projects/ngx-datatable/src/lib/components/row-detail/row-detail-template.directive.ts index bb40bf011..eadce44bf 100644 --- a/projects/ngx-datatable/src/lib/components/row-detail/row-detail-template.directive.ts +++ b/projects/ngx-datatable/src/lib/components/row-detail/row-detail-template.directive.ts @@ -1,8 +1,14 @@ import { Directive, TemplateRef } from '@angular/core'; +import { RowDetailContext } from '../../types/detail-context.type'; @Directive({ selector: '[ngx-datatable-row-detail-template]' }) -export class DatatableRowDetailTemplateDirective { - constructor(public template: TemplateRef) {} +export class DatatableRowDetailTemplateDirective { + static ngTemplateContextGuard( + directive: DatatableRowDetailTemplateDirective, + context: unknown + ): context is RowDetailContext { + return true; + } } diff --git a/projects/ngx-datatable/src/lib/components/row-detail/row-detail.directive.ts b/projects/ngx-datatable/src/lib/components/row-detail/row-detail.directive.ts index 4f623d783..bd4df35f3 100644 --- a/projects/ngx-datatable/src/lib/components/row-detail/row-detail.directive.ts +++ b/projects/ngx-datatable/src/lib/components/row-detail/row-detail.directive.ts @@ -1,21 +1,22 @@ import { ContentChild, Directive, EventEmitter, Input, Output, TemplateRef } from '@angular/core'; import { DatatableRowDetailTemplateDirective } from './row-detail-template.directive'; +import { RowDetailContext } from '../../types/detail-context.type'; @Directive({ selector: 'ngx-datatable-row-detail' }) -export class DatatableRowDetailDirective { +export class DatatableRowDetailDirective { /** * The detail row height is required especially * when virtual scroll is enabled. */ - @Input() rowHeight: number | ((row?: any, index?: number) => number) = 0; + @Input() rowHeight: number | ((row?: TRow, index?: number) => number) = 0; @Input('template') - _templateInput: TemplateRef; + _templateInput: TemplateRef>; @ContentChild(DatatableRowDetailTemplateDirective, { read: TemplateRef, static: true }) - _templateQuery: TemplateRef; + _templateQuery: TemplateRef>; - get template(): TemplateRef { + get template(): TemplateRef> { return this._templateInput || this._templateQuery; } @@ -27,7 +28,7 @@ export class DatatableRowDetailDirective { /** * Toggle the expansion of the row */ - toggleExpandRow(row: any): void { + toggleExpandRow(row: TRow): void { this.toggle.emit({ type: 'row', value: row diff --git a/projects/ngx-datatable/src/lib/directives/draggable.directive.ts b/projects/ngx-datatable/src/lib/directives/draggable.directive.ts index 0c3ef2815..6bbf8f6eb 100644 --- a/projects/ngx-datatable/src/lib/directives/draggable.directive.ts +++ b/projects/ngx-datatable/src/lib/directives/draggable.directive.ts @@ -1,6 +1,8 @@ import { Directive, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, Output, SimpleChanges } from '@angular/core'; import { fromEvent, Subscription } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; +import { TableColumn } from '../types/table-column.type'; +import { DraggableDragEvent } from '../types/drag-events.type'; /** * Draggable Directive for Angular2 @@ -13,13 +15,13 @@ import { takeUntil } from 'rxjs/operators'; @Directive({ selector: '[draggable]' }) export class DraggableDirective implements OnDestroy, OnChanges { @Input() dragEventTarget: any; - @Input() dragModel: any; + @Input() dragModel: TableColumn; @Input() dragX = true; @Input() dragY = true; - @Output() dragStart: EventEmitter = new EventEmitter(); - @Output() dragging: EventEmitter = new EventEmitter(); - @Output() dragEnd: EventEmitter = new EventEmitter(); + @Output() dragStart: EventEmitter = new EventEmitter(); + @Output() dragging: EventEmitter = new EventEmitter(); + @Output() dragEnd: EventEmitter = new EventEmitter(); element: HTMLElement; isDragging = false; diff --git a/projects/ngx-datatable/src/lib/directives/long-press.directive.ts b/projects/ngx-datatable/src/lib/directives/long-press.directive.ts index 7a880b42e..77f18ccca 100644 --- a/projects/ngx-datatable/src/lib/directives/long-press.directive.ts +++ b/projects/ngx-datatable/src/lib/directives/long-press.directive.ts @@ -2,16 +2,18 @@ import { Directive, EventEmitter, HostBinding, HostListener, Input, OnDestroy, O import { fromEvent, Observable, Subscription } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { MouseEvent } from '../events'; +import { TableColumn } from '../types/table-column.type'; + @Directive({ selector: '[long-press]' }) export class LongPressDirective implements OnDestroy { @Input() pressEnabled = true; - @Input() pressModel: any; + @Input() pressModel: TableColumn; @Input() duration = 500; - @Output() longPressStart: EventEmitter = new EventEmitter(); - @Output() longPressing: EventEmitter = new EventEmitter(); - @Output() longPressEnd: EventEmitter = new EventEmitter(); + @Output() longPressStart: EventEmitter<{event: MouseEvent; model: TableColumn}> = new EventEmitter(); + @Output() longPressing: EventEmitter<{event: MouseEvent; model: TableColumn}> = new EventEmitter(); + @Output() longPressEnd: EventEmitter<{model: TableColumn}> = new EventEmitter(); pressing: boolean; isLongPressing: boolean; diff --git a/projects/ngx-datatable/src/lib/directives/orderable.directive.ts b/projects/ngx-datatable/src/lib/directives/orderable.directive.ts index 00078d98a..19eeb50ba 100644 --- a/projects/ngx-datatable/src/lib/directives/orderable.directive.ts +++ b/projects/ngx-datatable/src/lib/directives/orderable.directive.ts @@ -3,7 +3,7 @@ import { ContentChildren, Directive, EventEmitter, - Inject, + Inject, KeyValueChangeRecord, KeyValueDiffer, KeyValueDiffers, OnDestroy, Output, @@ -11,17 +11,20 @@ import { } from '@angular/core'; import { DraggableDirective } from './draggable.directive'; import { DOCUMENT } from '@angular/common'; +import { TableColumn } from '../types/table-column.type'; +import { DraggableDragEvent } from '../types/drag-events.type'; +import { OrderableReorderEvent, OrderPosition, TargetChangedEvent } from '../types/orderable.types'; @Directive({ selector: '[orderable]' }) export class OrderableDirective implements AfterContentInit, OnDestroy { - @Output() reorder: EventEmitter = new EventEmitter(); - @Output() targetChanged: EventEmitter = new EventEmitter(); + @Output() reorder: EventEmitter = new EventEmitter(); + @Output() targetChanged: EventEmitter = new EventEmitter(); @ContentChildren(DraggableDirective, { descendants: true }) draggables: QueryList; - positions: any; - differ: any; + positions: Record; + differ: KeyValueDiffer; lastDraggingIndex: number; constructor(differs: KeyValueDiffers, @Inject(DOCUMENT) private document: any) { @@ -46,8 +49,9 @@ export class OrderableDirective implements AfterContentInit, OnDestroy { const diffs = this.differ.diff(this.createMapDiffs()); if (diffs) { - const subscribe = ({ currentValue, previousValue }: any) => { - unsubscribe({ previousValue }); + const subscribe = (record: KeyValueChangeRecord) => { + unsubscribe(record); + const { currentValue } = record; if (currentValue) { currentValue.dragStart.subscribe(this.onDragStart.bind(this)); @@ -56,7 +60,7 @@ export class OrderableDirective implements AfterContentInit, OnDestroy { } }; - const unsubscribe = ({ previousValue }: any) => { + const unsubscribe = ({ previousValue }: KeyValueChangeRecord) => { if (previousValue) { previousValue.dragStart.unsubscribe(); previousValue.dragging.unsubscribe(); @@ -86,7 +90,7 @@ export class OrderableDirective implements AfterContentInit, OnDestroy { } } - onDragging({ element, model, event }: any): void { + onDragging({ element, model, event }: DraggableDragEvent): void { const prevPos = this.positions[model.$$id]; const target = this.isTarget(model, event); @@ -108,7 +112,7 @@ export class OrderableDirective implements AfterContentInit, OnDestroy { } } - onDragEnd({ element, model, event }: any): void { + onDragEnd({ element, model, event }: DraggableDragEvent): void { const prevPos = this.positions[model.$$id]; const target = this.isTarget(model, event); @@ -124,7 +128,7 @@ export class OrderableDirective implements AfterContentInit, OnDestroy { element.style.left = 'auto'; } - isTarget(model: any, event: any): any { + isTarget(model: TableColumn, event: MouseEvent) { let i = 0; const x = event.x || event.clientX; const y = event.y || event.clientY; diff --git a/projects/ngx-datatable/src/lib/types/activate-event.type.ts b/projects/ngx-datatable/src/lib/types/activate-event.type.ts new file mode 100644 index 000000000..3625fb22f --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/activate-event.type.ts @@ -0,0 +1,15 @@ +import { TableColumn } from './table-column.type'; +import { TreeStatus } from '../components/body/body-cell.component'; +import { RowOrGroup } from './group.type'; + +export interface ActivateEvent { + type: 'checkbox' |'click' | 'dblclick' | 'keydown'; + event: Event; + row: RowOrGroup; + group: TRow[]; + rowHeight: number; + column: TableColumn; + value: any; + cellElement: HTMLElement; + treeStatus?: TreeStatus; +} diff --git a/projects/ngx-datatable/src/lib/types/cell-context.type.ts b/projects/ngx-datatable/src/lib/types/cell-context.type.ts new file mode 100644 index 000000000..339f6f97f --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/cell-context.type.ts @@ -0,0 +1,36 @@ +import { TableColumn } from './table-column.type'; +import { SortDirection } from './sort-direction.type'; +import { ActivateEvent } from './activate-event.type'; +import { TreeStatus } from '../components/body/body-cell.component'; +import { Observable } from 'rxjs'; +import { RowOrGroup } from './group.type'; + +export interface HeaderCellContext { + column: TableColumn; + sortDir: SortDirection | 'asc' | 'desc'; + sortFn: () => void; + allRowsSelected: boolean; + selectFn: () => void; +} + +export interface GroupContext { + group: RowOrGroup; + expanded: boolean; + rowIndex: number; +} + +export interface CellContext { + onCheckboxChangeFn: (event: Event) => void; + activateFn: (event: ActivateEvent) => void; + row: RowOrGroup; + group: TRow[]; + value: any; + column: TableColumn; + rowHeight: number; + isSelected: boolean; + rowIndex: number; + treeStatus: TreeStatus, + disable$: Observable; + onTreeAction: () => void; + expanded?: boolean; +} diff --git a/projects/ngx-datatable/src/lib/types/column-group-width.type.ts b/projects/ngx-datatable/src/lib/types/column-group-width.type.ts new file mode 100644 index 000000000..6812c9751 --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/column-group-width.type.ts @@ -0,0 +1,6 @@ +export interface ColumnGroupWidth { + left: number; + center: number; + right: number; + total: number; +} diff --git a/projects/ngx-datatable/src/lib/types/column-pin.type.ts b/projects/ngx-datatable/src/lib/types/column-pin.type.ts new file mode 100644 index 000000000..4f3c8e3c1 --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/column-pin.type.ts @@ -0,0 +1,8 @@ +import { TableColumn } from './table-column.type'; + +export type PinDirection = 'left' | 'center' | 'right'; + +export interface PinnedColumns { + type: PinDirection; + columns: TableColumn[]; +} diff --git a/projects/ngx-datatable/src/lib/types/detail-context.type.ts b/projects/ngx-datatable/src/lib/types/detail-context.type.ts new file mode 100644 index 000000000..7cd55a78d --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/detail-context.type.ts @@ -0,0 +1,9 @@ +import { Observable } from 'rxjs'; +import { RowOrGroup } from './group.type'; + +export interface RowDetailContext { + row: RowOrGroup; + expanded: boolean; + rowIndex: number; + disableRow$?: Observable +} diff --git a/projects/ngx-datatable/src/lib/types/drag-events.type.ts b/projects/ngx-datatable/src/lib/types/drag-events.type.ts index 60ab0a31e..1530a275b 100644 --- a/projects/ngx-datatable/src/lib/types/drag-events.type.ts +++ b/projects/ngx-datatable/src/lib/types/drag-events.type.ts @@ -1,3 +1,5 @@ +import { TableColumn } from './table-column.type'; + export type DragEventType = 'drag' | 'dragend' | 'dragenter' | 'dragleave' | 'dragover' | 'dragstart' | 'drop'; export interface DragEventData { @@ -8,3 +10,9 @@ export interface DragEventData { dragRow: any; dropRow?: any; } + +export interface DraggableDragEvent { + event: MouseEvent; + element: HTMLElement; + model: TableColumn; +} diff --git a/projects/ngx-datatable/src/lib/types/footer-context.ts b/projects/ngx-datatable/src/lib/types/footer-context.ts new file mode 100644 index 000000000..66acd4c18 --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/footer-context.ts @@ -0,0 +1,7 @@ +export interface FooterContext { + rowCount: number; + pageSize: number; + selectedCount: number; + curPage: number; + offset: number; +} diff --git a/projects/ngx-datatable/src/lib/types/group.type.ts b/projects/ngx-datatable/src/lib/types/group.type.ts new file mode 100644 index 000000000..99f767a4f --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/group.type.ts @@ -0,0 +1,10 @@ +/** A Group row */ +export interface Group { + /** The value by which to rows are grouped. */ + key: TRow[keyof TRow]; + /** All rows that are part of the group. */ + value: TRow[]; +} + +/** Type for either a row or a group */ +export type RowOrGroup = TRow | Group; diff --git a/projects/ngx-datatable/src/lib/types/orderable.types.ts b/projects/ngx-datatable/src/lib/types/orderable.types.ts new file mode 100644 index 000000000..bf5f9877f --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/orderable.types.ts @@ -0,0 +1,26 @@ +import { TableColumn } from './table-column.type'; + +export interface OrderPosition { + left: number; + right: number; + index: number; + element: HTMLElement; +} + +export interface OrderableReorderEvent { + prevIndex: number; + newIndex: number; + model: TableColumn; +} + +export interface ReorderEvent { + column: TableColumn; + prevValue: number; + newValue: number; +} + +export interface TargetChangedEvent { + newIndex?: number; + prevIndex: number; + initialIndex: number; +} diff --git a/projects/ngx-datatable/src/lib/types/page-event.type.ts b/projects/ngx-datatable/src/lib/types/page-event.type.ts new file mode 100644 index 000000000..449479d9b --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/page-event.type.ts @@ -0,0 +1,14 @@ +export interface PageEvent { + count: number; + pageSize: number; + limit: number; + offset: number; +} + +export interface BodyPageEvent { + offset: number; +} + +export interface PagerPageEvent { + page: number; +} diff --git a/projects/ngx-datatable/src/lib/types/pages.type.ts b/projects/ngx-datatable/src/lib/types/pages.type.ts new file mode 100644 index 000000000..568b38e4e --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/pages.type.ts @@ -0,0 +1,4 @@ +export interface Page { + number: number; + text: string; +} diff --git a/projects/ngx-datatable/src/lib/types/resize.type.ts b/projects/ngx-datatable/src/lib/types/resize.type.ts new file mode 100644 index 000000000..7a65cc0a5 --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/resize.type.ts @@ -0,0 +1,7 @@ +import { TableColumn } from './table-column.type'; + +export interface ColumnResizeEvent { + column: TableColumn; + prevValue: number; + newValue: number; +} diff --git a/projects/ngx-datatable/src/lib/types/scroll.type.ts b/projects/ngx-datatable/src/lib/types/scroll.type.ts new file mode 100644 index 000000000..b496e6e28 --- /dev/null +++ b/projects/ngx-datatable/src/lib/types/scroll.type.ts @@ -0,0 +1,4 @@ +export interface ScrollEvent { + offsetY: number; + offsetX: number; +} diff --git a/projects/ngx-datatable/src/lib/types/sort-direction.type.ts b/projects/ngx-datatable/src/lib/types/sort-direction.type.ts index 4344f2bb7..ff38c64a9 100644 --- a/projects/ngx-datatable/src/lib/types/sort-direction.type.ts +++ b/projects/ngx-datatable/src/lib/types/sort-direction.type.ts @@ -1,4 +1,17 @@ +import { TableColumn } from './table-column.type'; +import { SortPropDir } from './sort-prop-dir.type'; + export enum SortDirection { asc = 'asc', desc = 'desc' } + +export interface InnerSortEvent { + column: TableColumn; + prevValue: SortDirection; + newValue: SortDirection; +} + +export interface SortEvent extends InnerSortEvent { + sorts: SortPropDir[]; +} diff --git a/projects/ngx-datatable/src/lib/types/sort-prop-dir.type.ts b/projects/ngx-datatable/src/lib/types/sort-prop-dir.type.ts index 3bfe9d2d2..7d4e1989e 100644 --- a/projects/ngx-datatable/src/lib/types/sort-prop-dir.type.ts +++ b/projects/ngx-datatable/src/lib/types/sort-prop-dir.type.ts @@ -2,6 +2,6 @@ import { SortDirection } from './sort-direction.type'; import { TableColumnProp } from './table-column.type'; export interface SortPropDir { - dir: SortDirection; + dir: SortDirection | 'desc' | 'asc'; prop: TableColumnProp; } diff --git a/projects/ngx-datatable/src/lib/types/table-column.type.ts b/projects/ngx-datatable/src/lib/types/table-column.type.ts index b137aa470..412bb7aa6 100644 --- a/projects/ngx-datatable/src/lib/types/table-column.type.ts +++ b/projects/ngx-datatable/src/lib/types/table-column.type.ts @@ -1,5 +1,6 @@ -import { PipeTransform } from '@angular/core'; +import { PipeTransform, TemplateRef } from '@angular/core'; import { ValueGetter } from '../utils/column-prop-getters'; +import { HeaderCellContext } from './cell-context.type'; /** * Column property that indicates how to retrieve this column's @@ -120,6 +121,15 @@ export interface TableColumn { */ draggable?: boolean; + /** @internal */ + dragging?: boolean; + + /** @internal */ + isTarget?: boolean; + + /** @internal */ + targetMarkerContext?: any; + /** * Whether the column can automatically resize to fill space in the table. * @@ -164,7 +174,7 @@ export interface TableColumn { * * @memberOf TableColumn */ - headerTemplate?: any; + headerTemplate?: TemplateRef; /** * Tree toggle template ref diff --git a/projects/ngx-datatable/src/lib/utils/column-helper.ts b/projects/ngx-datatable/src/lib/utils/column-helper.ts index a2b7560e6..fd11cf9a8 100644 --- a/projects/ngx-datatable/src/lib/utils/column-helper.ts +++ b/projects/ngx-datatable/src/lib/utils/column-helper.ts @@ -82,10 +82,10 @@ export function isNullOrUndefined(value: T | null | undefined): value is null /** * Translates templates definitions to objects */ -export function translateTemplates(templates: DataTableColumnDirective[]): any[] { - const result: any[] = []; +export function translateTemplates(templates: DataTableColumnDirective[]): TableColumn[] { + const result: TableColumn[] = []; for (const temp of templates) { - const col: any = {}; + const col: TableColumn = {}; const props = Object.getOwnPropertyNames(temp); for (const prop of props) { diff --git a/projects/ngx-datatable/src/lib/utils/column.ts b/projects/ngx-datatable/src/lib/utils/column.ts index 4c50cf78f..ebdfa6fa1 100644 --- a/projects/ngx-datatable/src/lib/utils/column.ts +++ b/projects/ngx-datatable/src/lib/utils/column.ts @@ -1,8 +1,12 @@ +import { TableColumn } from '../types/table-column.type'; +import { PinnedColumns } from '../types/column-pin.type'; +import { ColumnGroupWidth } from '../types/column-group-width.type'; + /** * Returns the columns by pin. */ -export function columnsByPin(cols: any[]) { - const ret: { left: any; center: any; right: any } = { +export function columnsByPin(cols: TableColumn[]) { + const ret: { left: TableColumn[]; center: TableColumn[]; right: TableColumn[] } = { left: [], center: [], right: [] @@ -26,7 +30,7 @@ export function columnsByPin(cols: any[]) { /** * Returns the widths of all group sets of a column */ -export function columnGroupWidths(groups: any, all: any) { +export function columnGroupWidths(groups: any, all: any): ColumnGroupWidth { return { left: columnTotalWidth(groups.left), center: columnTotalWidth(groups.center), @@ -66,13 +70,11 @@ export function columnsTotalWidth(columns: any, prop?: any) { return totalWidth; } -export function columnsByPinArr(val: any) { - const colsByPinArr = []; +export function columnsByPinArr(val: TableColumn[]): PinnedColumns[] { const colsByPin = columnsByPin(val); - - colsByPinArr.push({ type: 'left', columns: colsByPin.left }); - colsByPinArr.push({ type: 'center', columns: colsByPin.center }); - colsByPinArr.push({ type: 'right', columns: colsByPin.right }); - - return colsByPinArr; + return [ + { type: 'left' as const, columns: colsByPin.left }, + { type: 'center' as const, columns: colsByPin.center }, + { type: 'right' as const, columns: colsByPin.right } + ]; } diff --git a/projects/ngx-datatable/src/lib/utils/selection.ts b/projects/ngx-datatable/src/lib/utils/selection.ts index dd7915a75..0c7db48a7 100644 --- a/projects/ngx-datatable/src/lib/utils/selection.ts +++ b/projects/ngx-datatable/src/lib/utils/selection.ts @@ -10,13 +10,12 @@ export function selectRows(selected: any[], row: any, comparefn: any) { return selected; } -export function selectRowsBetween( - selected: any[], - rows: any[], +export function selectRowsBetween( + selected: TRow[], + rows: TRow[], index: number, - prevIndex: number, - comparefn: any -): any[] { + prevIndex: number +): TRow[] { const reverse = index < prevIndex; for (let i = 0; i < rows.length; i++) { diff --git a/projects/ngx-datatable/src/lib/utils/sort.ts b/projects/ngx-datatable/src/lib/utils/sort.ts index 7a31f2d53..0f2dfbe0b 100644 --- a/projects/ngx-datatable/src/lib/utils/sort.ts +++ b/projects/ngx-datatable/src/lib/utils/sort.ts @@ -5,7 +5,7 @@ import { SortPropDir } from '../types/sort-prop-dir.type'; /** * Gets the next sort direction */ -export function nextSortDir(sortType: SortType, current: SortDirection): SortDirection | undefined { +export function nextSortDir(sortType: SortType, current: SortDirection | 'desc' | 'asc'): SortDirection | undefined { if (sortType === SortType.single) { if (current === SortDirection.asc) { return SortDirection.desc; diff --git a/projects/ngx-datatable/src/lib/utils/translate.ts b/projects/ngx-datatable/src/lib/utils/translate.ts index a78d3478d..2f25665bc 100644 --- a/projects/ngx-datatable/src/lib/utils/translate.ts +++ b/projects/ngx-datatable/src/lib/utils/translate.ts @@ -3,22 +3,25 @@ import { camelCase } from './camel-case'; // browser detection and prefixing tools const transform = typeof window !== 'undefined' ? getVendorPrefixedName('transform') : undefined; -const backfaceVisibility = typeof window !== 'undefined' ? getVendorPrefixedName('backfaceVisibility') : undefined; const hasCSSTransforms = typeof window !== 'undefined' ? !!getVendorPrefixedName('transform') : undefined; const hasCSS3DTransforms = typeof window !== 'undefined' ? !!getVendorPrefixedName('perspective') : undefined; const ua = typeof window !== 'undefined' ? window.navigator.userAgent : 'Chrome'; const isSafari = /Safari\//.test(ua) && !/Chrome\//.test(ua); -export function translateXY(styles: any, x: number, y: number) { +export function translateXY(x: number, y: number): Record { if (typeof transform !== 'undefined' && hasCSSTransforms) { if (!isSafari && hasCSS3DTransforms) { - styles[transform] = `translate3d(${x}px, ${y}px, 0)`; - styles[backfaceVisibility] = 'hidden'; + return { + transform: `translate3d(${x}px, ${y}px, 0)`, + backfaceVisibility: 'hidden' + } } else { - styles[camelCase(transform)] = `translate(${x}px, ${y}px)`; + return { [camelCase(transform)]: `translate(${x}px, ${y}px)` } } } else { - styles.top = `${y}px`; - styles.left = `${x}px`; + return { + top: `${y}px`, + left: `${x}px` + } } } diff --git a/projects/ngx-datatable/src/public-api.ts b/projects/ngx-datatable/src/public-api.ts index 2d6ba6b82..6ea3c6daa 100644 --- a/projects/ngx-datatable/src/public-api.ts +++ b/projects/ngx-datatable/src/public-api.ts @@ -44,14 +44,26 @@ export * from './lib/services/dimensions-helper.service'; export * from './lib/services/column-changes.service'; // types +export * from './lib/types/activate-event.type'; +export * from './lib/types/cell-context.type'; +export * from './lib/types/click.type' +export * from './lib/types/column-group-width.type'; export * from './lib/types/column-mode.type'; +export * from './lib/types/column-pin.type'; +export * from './lib/types/contextmenu.type'; +export * from './lib/types/detail-context.type' +export * from './lib/types/drag-events.type'; +export * from './lib/types/footer-context'; +export * from './lib/types/group.type'; +export * from './lib/types/orderable.types'; +export * from './lib/types/page-event.type'; +export * from './lib/types/pages.type'; +export * from './lib/types/resize.type'; +export * from './lib/types/selection.type'; export * from './lib/types/sort.type'; export * from './lib/types/sort-direction.type'; -export * from './lib/types/selection.type'; -export * from './lib/types/click.type'; -export * from './lib/types/table-column.type'; export * from './lib/types/sort-prop-dir.type'; -export * from './lib/types/contextmenu.type'; +export * from './lib/types/table-column.type'; // utils export * from './lib/utils/id'; diff --git a/src/app/basic/basic-auto.component.ts b/src/app/basic/basic-auto.component.ts index ab793b4cb..df60b731b 100644 --- a/src/app/basic/basic-auto.component.ts +++ b/src/app/basic/basic-auto.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'basic-auto-demo', @@ -32,11 +33,11 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class BasicAutoComponent { - rows = []; + rows: Employee[] = []; loadingIndicator = true; reorderable = true; - columns = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company', sortable: false }]; + columns: TableColumn[] = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company', sortable: false }]; ColumnMode = ColumnMode; diff --git a/src/app/basic/basic-fixed.component.ts b/src/app/basic/basic-fixed.component.ts index 9f7f5ac3d..e73238007 100644 --- a/src/app/basic/basic-fixed.component.ts +++ b/src/app/basic/basic-fixed.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'basic-fixed-demo', @@ -30,8 +31,8 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class BasicFixedComponent { - rows = []; - columns = [{ prop: 'name' }, { name: 'Company' }, { name: 'Gender' }]; + rows: Employee[] = []; + columns: TableColumn[] = [{ prop: 'name' }, { name: 'Company' }, { name: 'Gender' }]; ColumnMode = ColumnMode; diff --git a/src/app/basic/bootstrap.component.ts b/src/app/basic/bootstrap.component.ts index 6922bf7a7..ee0da49bd 100644 --- a/src/app/basic/bootstrap.component.ts +++ b/src/app/basic/bootstrap.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'basic-bootstrap-theme-demo', @@ -35,11 +36,11 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class BootstrapThemeComponent { - rows = []; + rows: Employee[] = []; loadingIndicator = true; reorderable = true; - columns = [ + columns: TableColumn[] = [ { prop: 'name', summaryFunc: () => null }, { name: 'Gender', summaryFunc: cells => this.summaryForGender(cells) }, { name: 'Company', summaryFunc: () => null } diff --git a/src/app/basic/contextmenu.component.ts b/src/app/basic/contextmenu.component.ts index 9555810d0..9c0dbc72e 100644 --- a/src/app/basic/contextmenu.component.ts +++ b/src/app/basic/contextmenu.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'contextmenu-demo', @@ -44,9 +45,9 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class ContextMenuDemoComponent { - rows = []; + rows: Employee[] = []; - columns = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company' }]; + columns: TableColumn[] = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company' }]; rawEvent: any; contextmenuRow: any; diff --git a/src/app/basic/css.component.ts b/src/app/basic/css.component.ts index e7012bbdf..a36ecf7ec 100644 --- a/src/app/basic/css.component.ts +++ b/src/app/basic/css.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { FullEmployee } from "../data.model"; @Component({ selector: 'row-css-demo', @@ -33,9 +34,8 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class RowCssComponent { - rows = []; + rows: FullEmployee[] = []; expanded = {}; - timeout: any; ColumnMode = ColumnMode; diff --git a/src/app/basic/dark-theme.component.ts b/src/app/basic/dark-theme.component.ts index 06b63bc58..15c908371 100644 --- a/src/app/basic/dark-theme.component.ts +++ b/src/app/basic/dark-theme.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'basic-dark-theme-demo', @@ -34,11 +35,11 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class DarkThemeComponent { - rows = []; + rows: Employee[] = []; loadingIndicator = true; reorderable = true; - columns = [ + columns: TableColumn[] = [ { prop: 'name', summaryFunc: () => null }, { name: 'Gender', summaryFunc: cells => this.summaryForGender(cells) }, { name: 'Company', summaryFunc: () => null } diff --git a/src/app/basic/disabled-rows.component.ts b/src/app/basic/disabled-rows.component.ts index 43792930b..22e4e5f2c 100644 --- a/src/app/basic/disabled-rows.component.ts +++ b/src/app/basic/disabled-rows.component.ts @@ -1,5 +1,7 @@ import { Component } from '@angular/core'; import { ColumnMode, SelectionType } from 'projects/ngx-datatable/src/public-api'; +import { FullEmployee } from "../data.model"; +import { BehaviorSubject } from "rxjs"; @Component({ selector: 'disabled-rows-demo', @@ -60,7 +62,7 @@ import { ColumnMode, SelectionType } from 'projects/ngx-datatable/src/public-api ` }) export class DisabledRowsComponent { - rows = []; + rows: (FullEmployee & {isDisabled?: boolean}) [] = []; ColumnMode = ColumnMode; SelectionType = SelectionType; @@ -82,21 +84,17 @@ export class DisabledRowsComponent { req.send(); } - isRowDisabled(row: any) { - if (!row.isDisabled && row.age < 40) { - return false; - } else { - return true; - } + isRowDisabled(row: FullEmployee & {isDisabled: boolean}) { + return !(!row.isDisabled && row.age < 40); } - disableRow(rowIndex, disableRow$) { + disableRow(rowIndex: number, disableRow$: BehaviorSubject) { this.rows[rowIndex].isDisabled = true; this.rows = [...this.rows]; disableRow$.next(true); } - updateValue(event, cell, rowIndex, disableRow$) { + updateValue(event, cell, rowIndex: number, disableRow$: BehaviorSubject) { this.rows[rowIndex][cell] = event.target.value; this.rows = [...this.rows]; if (disableRow$ && cell === 'age' && this.rows[rowIndex][cell] > 40) { diff --git a/src/app/basic/dynamic-height.component.ts b/src/app/basic/dynamic-height.component.ts index d66a1cc85..cbba79050 100644 --- a/src/app/basic/dynamic-height.component.ts +++ b/src/app/basic/dynamic-height.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { FullEmployee } from "../data.model"; @Component({ selector: 'dynamic-height-demo', @@ -33,7 +34,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class DynamicHeightComponent { - rows = []; + rows: FullEmployee[] = []; expanded = {}; timeout: any; diff --git a/src/app/basic/empty.component.ts b/src/app/basic/empty.component.ts index 82d423ffb..62f5dd13a 100644 --- a/src/app/basic/empty.component.ts +++ b/src/app/basic/empty.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; @Component({ selector: 'empty-demo', @@ -30,6 +30,6 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class BasicEmptyComponent { - columns = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company', sortable: false }]; + columns: TableColumn[] = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company', sortable: false }]; ColumnMode = ColumnMode; } diff --git a/src/app/basic/filter.component.ts b/src/app/basic/filter.component.ts index 3e2bc8700..4b0085134 100644 --- a/src/app/basic/filter.component.ts +++ b/src/app/basic/filter.component.ts @@ -1,6 +1,7 @@ import { Component, ViewChild } from '@angular/core'; import { DatatableComponent } from '../../../projects/ngx-datatable/src/lib/components/datatable.component'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'filter-demo', @@ -39,12 +40,12 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class FilterBarComponent { - rows = []; + rows: Employee[] = []; - temp = []; + temp: Employee[] = []; - columns = [{ prop: 'name' }, { name: 'Company' }, { name: 'Gender' }]; - @ViewChild(DatatableComponent) table: DatatableComponent; + columns: TableColumn[] = [{ prop: 'name' }, { name: 'Company' }, { name: 'Gender' }]; + @ViewChild(DatatableComponent) table: DatatableComponent; ColumnMode = ColumnMode; @@ -72,13 +73,10 @@ export class FilterBarComponent { updateFilter(event) { const val = event.target.value.toLowerCase(); - // filter our data - const temp = this.temp.filter(function(d) { + // filter our data and update the rows + this.rows = this.temp.filter(function (d) { return d.name.toLowerCase().indexOf(val) !== -1 || !val; }); - - // update the rows - this.rows = temp; // Whenever the filter changes, always go back to the first page this.table.offset = 0; } diff --git a/src/app/basic/footer.component.ts b/src/app/basic/footer.component.ts index b075b759a..cf67976ef 100644 --- a/src/app/basic/footer.component.ts +++ b/src/app/basic/footer.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'footer-demo', @@ -46,9 +47,9 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class FooterDemoComponent { - rows = []; + rows: Employee[] = []; - columns = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company' }]; + columns: TableColumn[] = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company' }]; ColumnMode = ColumnMode; diff --git a/src/app/basic/fullscreen.component.ts b/src/app/basic/fullscreen.component.ts index d6b3b608c..6ec840dee 100644 --- a/src/app/basic/fullscreen.component.ts +++ b/src/app/basic/fullscreen.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { FullEmployee } from "../data.model"; @Component({ selector: 'full-screen-demo', @@ -38,7 +39,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class FullScreenComponent { - rows = []; + rows: FullEmployee[] = []; ColumnMode = ColumnMode; diff --git a/src/app/basic/inline.component.ts b/src/app/basic/inline.component.ts index 8329d588d..08061af6d 100644 --- a/src/app/basic/inline.component.ts +++ b/src/app/basic/inline.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'inline-edit-demo', @@ -75,7 +76,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; }) export class InlineEditComponent { editing = {}; - rows = []; + rows: Employee[] = []; ColumnMode = ColumnMode; @@ -96,7 +97,7 @@ export class InlineEditComponent { req.send(); } - updateValue(event, cell, rowIndex) { + updateValue(event, cell, rowIndex: number) { console.log('inline editing rowIndex', rowIndex); this.editing[rowIndex + '-' + cell] = false; this.rows[rowIndex][cell] = event.target.value; diff --git a/src/app/basic/live.component.ts b/src/app/basic/live.component.ts index 179993621..4dae5c32d 100644 --- a/src/app/basic/live.component.ts +++ b/src/app/basic/live.component.ts @@ -1,5 +1,6 @@ import { ChangeDetectorRef, Component, ViewChild } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, DatatableComponent } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'live-data-demo', @@ -41,13 +42,13 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class LiveDataComponent { - @ViewChild('mydatatable') mydatatable: any; + @ViewChild('mydatatable') mydatatable: DatatableComponent; count = 50; - rows: any[] = []; + rows: (Employee & {updated: string})[] = []; active = true; - temp: any[] = []; - cols: any = ['name', 'gender', 'company']; + temp: (Employee & {updated: string})[] = []; + cols = ['name', 'gender', 'company']; ColumnMode = ColumnMode; diff --git a/src/app/basic/multiple.component.ts b/src/app/basic/multiple.component.ts index 21926e932..9da1f6bf6 100644 --- a/src/app/basic/multiple.component.ts +++ b/src/app/basic/multiple.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; @Component({ selector: 'multiple-tables-demo', @@ -40,9 +40,9 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class MultipleTablesComponent { - columns1 = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company' }]; + columns1: TableColumn[] = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company' }]; - columns2 = [{ prop: 'name', name: 'Name' }, { name: 'Gender' }]; + columns2: TableColumn[] = [{ prop: 'name', name: 'Name' }, { name: 'Gender' }]; rows1 = [ { name: 'Larry', gender: 'Male', company: 'Cisco' }, diff --git a/src/app/basic/responsive.component.ts b/src/app/basic/responsive.component.ts index 36631bf2d..bde5aa601 100644 --- a/src/app/basic/responsive.component.ts +++ b/src/app/basic/responsive.component.ts @@ -1,5 +1,6 @@ import { Component, ViewChild, ViewEncapsulation } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, DatatableComponent } from 'projects/ngx-datatable/src/public-api'; +import { FullEmployee } from "../data.model"; @Component({ selector: 'responsive-demo', @@ -115,9 +116,9 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; encapsulation: ViewEncapsulation.None }) export class ResponsiveComponent { - @ViewChild('myTable') table: any; + @ViewChild('myTable') table: DatatableComponent; - rows: any[] = []; + rows: FullEmployee[] = []; expanded: any = {}; timeout: any; diff --git a/src/app/basic/row-detail.component.ts b/src/app/basic/row-detail.component.ts index 8a8d6a85b..fa034993e 100644 --- a/src/app/basic/row-detail.component.ts +++ b/src/app/basic/row-detail.component.ts @@ -1,5 +1,6 @@ import { Component, ViewChild, ViewEncapsulation } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, DatatableComponent } from 'projects/ngx-datatable/src/public-api'; +import { FullEmployee } from "../data.model"; @Component({ selector: 'row-details-demo', @@ -89,9 +90,9 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; encapsulation: ViewEncapsulation.None }) export class RowDetailsComponent { - @ViewChild('myTable') table: any; + @ViewChild('myTable') table: DatatableComponent; - rows: any[] = []; + rows: FullEmployee[] = []; expanded: any = {}; timeout: any; diff --git a/src/app/basic/row-grouping.component.ts b/src/app/basic/row-grouping.component.ts index 6def7d1c3..b9d187730 100644 --- a/src/app/basic/row-grouping.component.ts +++ b/src/app/basic/row-grouping.component.ts @@ -1,7 +1,6 @@ -import { Component, ViewChild, ViewEncapsulation } from '@angular/core'; -import { NgStyle } from '@angular/common'; - -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Component, ViewChild } from '@angular/core'; +import { ColumnMode, DatatableComponent } from 'projects/ngx-datatable/src/public-api'; +import { GroupedEmployee } from '../data.model'; import { SelectionType } from './../../../projects/ngx-datatable/src/lib/types/selection.type'; @Component({ @@ -122,15 +121,10 @@ import { SelectionType } from './../../../projects/ngx-datatable/src/lib/types/s ` }) export class RowGroupingComponent { - @ViewChild('myTable') table: any; - - funder = []; - calculated = []; - pending = []; - groups = []; + @ViewChild('myTable') table: DatatableComponent; - editing = {}; - rows = []; + editing: Record = {}; + rows: GroupedEmployee[] = []; ColumnMode = ColumnMode; SelectionType = SelectionType; @@ -152,17 +146,6 @@ export class RowGroupingComponent { req.send(); } - getGroupRowHeight(group, rowHeight) { - let style = {}; - - style = { - height: group.length * 40 + 'px', - width: '100%' - }; - - return style; - } - checkGroup(event, row, rowIndex, group) { let groupStatus = 'Pending'; let expectedPaymentDealtWith = true; diff --git a/src/app/basic/rx.component.ts b/src/app/basic/rx.component.ts index 9fdccfe5d..173309623 100644 --- a/src/app/basic/rx.component.ts +++ b/src/app/basic/rx.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; import { Observable } from 'rxjs'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'rx-demo', @@ -28,9 +29,9 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class RxDemoComponent { - rows: Observable; + rows: Observable; - columns = [{ name: 'Name' }, { name: 'Gender' }, { name: 'Company' }]; + columns: TableColumn[] = [{ name: 'Name' }, { name: 'Gender' }, { name: 'Company' }]; ColumnMode = ColumnMode; diff --git a/src/app/basic/scrolling-dynamically.component.ts b/src/app/basic/scrolling-dynamically.component.ts index 367709ea0..99b011f60 100644 --- a/src/app/basic/scrolling-dynamically.component.ts +++ b/src/app/basic/scrolling-dynamically.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'scrolling-dynamically-demo', @@ -77,8 +78,8 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class ScollingDynamicallyComponent { - editing = {}; - rows = []; + editing: Record = {}; + rows: Employee[] = []; ColumnMode = ColumnMode; diff --git a/src/app/basic/scrolling.component.ts b/src/app/basic/scrolling.component.ts index 0a70dbe08..af726694e 100644 --- a/src/app/basic/scrolling.component.ts +++ b/src/app/basic/scrolling.component.ts @@ -1,4 +1,5 @@ import { Component } from '@angular/core'; +import { FullEmployee } from "../data.model"; @Component({ selector: 'horz-vert-scrolling-demo', @@ -35,7 +36,7 @@ import { Component } from '@angular/core'; ` }) export class HorzVertScrollingComponent { - rows = []; + rows: FullEmployee[] = []; constructor() { this.fetch(data => { diff --git a/src/app/basic/tabs.component.ts b/src/app/basic/tabs.component.ts index 92be7f227..1edd2c899 100644 --- a/src/app/basic/tabs.component.ts +++ b/src/app/basic/tabs.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { FullEmployee } from "../data.model"; @Component({ selector: 'tabs-demo', @@ -66,7 +67,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class TabsDemoComponent { - rows = []; + rows: FullEmployee[] = []; tab1 = true; tab2 = false; diff --git a/src/app/basic/virtual.component.ts b/src/app/basic/virtual.component.ts index ef6f57d3b..882206e58 100644 --- a/src/app/basic/virtual.component.ts +++ b/src/app/basic/virtual.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { FullEmployee } from "../data.model"; @Component({ selector: 'virtual-scroll-demo', @@ -42,7 +43,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class VirtualScrollComponent { - rows; + rows: FullEmployee[]; expanded = {}; timeout: any; diff --git a/src/app/columns/column-flex.component.ts b/src/app/columns/column-flex.component.ts index 153060293..378f4968d 100644 --- a/src/app/columns/column-flex.component.ts +++ b/src/app/columns/column-flex.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'column-flex-demo', @@ -44,7 +45,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class ColumnFlexComponent { - rows = []; + rows: Employee[] = []; ColumnMode = ColumnMode; diff --git a/src/app/columns/column-force.component.ts b/src/app/columns/column-force.component.ts index e6a49e40c..42b59e588 100644 --- a/src/app/columns/column-force.component.ts +++ b/src/app/columns/column-force.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'column-force-demo', @@ -44,7 +45,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class ColumnForceComponent { - rows = []; + rows: Employee[] = []; ColumnMode = ColumnMode; diff --git a/src/app/columns/column-reorder.component.ts b/src/app/columns/column-reorder.component.ts index c2289d99b..bc97fb3ee 100644 --- a/src/app/columns/column-reorder.component.ts +++ b/src/app/columns/column-reorder.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'column-reorder-demo', @@ -56,12 +57,12 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class ColumnReorderComponent { - rows = []; + rows: Employee[] = []; loadingIndicator = true; reorderable = true; swapColumns = false; - columns = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company', sortable: false }]; + columns: TableColumn[] = [{ prop: 'name' }, { name: 'Gender' }, { name: 'Company', sortable: false }]; ColumnMode = ColumnMode; diff --git a/src/app/columns/column-standard.component.ts b/src/app/columns/column-standard.component.ts index cc49fee5a..d11599657 100644 --- a/src/app/columns/column-standard.component.ts +++ b/src/app/columns/column-standard.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'column-standard-demo', @@ -44,7 +45,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class ColumnStandardComponent { - rows = []; + rows: Employee[] = []; ColumnMode = ColumnMode; diff --git a/src/app/columns/column-toggle.component.ts b/src/app/columns/column-toggle.component.ts index 9298d553e..a4546d344 100644 --- a/src/app/columns/column-toggle.component.ts +++ b/src/app/columns/column-toggle.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'column-toggle-demo', @@ -41,7 +42,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class ColumnToggleComponent { - rows = [ + rows: Employee[] = [ { name: 'Claudine Neal', gender: 'female', @@ -54,13 +55,13 @@ export class ColumnToggleComponent { } ]; - columns = [{ name: 'Name' }, { name: 'Gender' }, { name: 'Company' }]; + columns: TableColumn[] = [{ name: 'Name' }, { name: 'Gender' }, { name: 'Company' }]; - allColumns = [{ name: 'Name' }, { name: 'Gender' }, { name: 'Company' }]; + allColumns: TableColumn[] = [{ name: 'Name' }, { name: 'Gender' }, { name: 'Company' }]; ColumnMode = ColumnMode; - toggle(col) { + toggle(col: TableColumn) { const isChecked = this.isChecked(col); if (isChecked) { @@ -70,7 +71,7 @@ export class ColumnToggleComponent { } } - isChecked(col) { + isChecked(col: TableColumn) { return ( this.columns.find(c => c.name === col.name) !== undefined ); diff --git a/src/app/columns/pinning.component.ts b/src/app/columns/pinning.component.ts index e6a0f1c07..4cf2ee658 100644 --- a/src/app/columns/pinning.component.ts +++ b/src/app/columns/pinning.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { FullEmployee } from "../data.model"; @Component({ selector: 'column-pinning-demo', @@ -37,7 +38,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class ColumnPinningComponent { - rows = []; + rows: FullEmployee[] = []; ColumnMode = ColumnMode; diff --git a/src/app/data.model.ts b/src/app/data.model.ts new file mode 100644 index 000000000..ddd130197 --- /dev/null +++ b/src/app/data.model.ts @@ -0,0 +1,30 @@ +export interface Employee { + name: string; + gender: string; + company: string; + age?: number; +} + +export interface FullEmployee { + id: number; + name: string; + gender: string; + age: number; + address: { + state: string; + city: string; + } +} + +export interface GroupedEmployee { + exppayyes?: number; + exppayno?: number; + exppaypending?: number; + source?: string; + name: string; + gender: string; + company: string; + age: number; + comment?: string; + groupcomment?: string; +} diff --git a/src/app/paging/mock-server-results-service.ts b/src/app/paging/mock-server-results-service.ts index d80920e70..5365eb158 100644 --- a/src/app/paging/mock-server-results-service.ts +++ b/src/app/paging/mock-server-results-service.ts @@ -2,10 +2,10 @@ import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { delay, map } from 'rxjs/operators'; import { PagedData } from './model/paged-data'; -import { CorporateEmployee } from './model/corporate-employee'; import { Page } from './model/page'; import companyData from 'src/assets/data/company.json'; +import { Employee } from "../data.model"; /** * A server used to mock a paged data result from a server @@ -17,7 +17,7 @@ export class MockServerResultsService { * @param page The selected page * @returns An observable containing the employee data */ - public getResults(page: Page): Observable> { + public getResults(page: Page): Observable> { return of(companyData) .pipe(map(d => this.getPagedData(page))) .pipe(delay(1000 * Math.random())); @@ -28,18 +28,15 @@ export class MockServerResultsService { * @param page The page data used to get the selected data from companyData * @returns An array of the selected data and page */ - private getPagedData(page: Page): PagedData { - const pagedData = new PagedData(); + private getPagedData(page: Page): PagedData { + const data: Employee[] = [] page.totalElements = companyData.length; page.totalPages = page.totalElements / page.size; const start = page.pageNumber * page.size; const end = Math.min(start + page.size, page.totalElements); for (let i = start; i < end; i++) { - const jsonObj = companyData[i]; - const employee = new CorporateEmployee(jsonObj.name, jsonObj.gender, jsonObj.company, jsonObj.age); - pagedData.data.push(employee); + data.push(companyData[i]); } - pagedData.page = page; - return pagedData; + return { page, data }; } } diff --git a/src/app/paging/model/corporate-employee.ts b/src/app/paging/model/corporate-employee.ts deleted file mode 100644 index 692640184..000000000 --- a/src/app/paging/model/corporate-employee.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * A model for an individual corporate employee - */ -export class CorporateEmployee { - name: string; - gender: string; - company: string; - age: number; - - constructor(name: string, gender: string, company: string, age: number) { - this.name = name; - this.gender = gender; - this.company = company; - this.age = age; - } -} diff --git a/src/app/paging/model/page.ts b/src/app/paging/model/page.ts index 84421da31..98fb35aff 100644 --- a/src/app/paging/model/page.ts +++ b/src/app/paging/model/page.ts @@ -1,13 +1,13 @@ /** * An object used to get page information from the server */ -export class Page { +export interface Page { // The number of elements in the page - size = 0; + size: number; // The total number of elements - totalElements = 0; + totalElements: number; // The total number of pages - totalPages = 0; + totalPages: number; // The current page number - pageNumber = 0; + pageNumber: number; } diff --git a/src/app/paging/model/paged-data.ts b/src/app/paging/model/paged-data.ts index 7121734d1..886cde0f8 100644 --- a/src/app/paging/model/paged-data.ts +++ b/src/app/paging/model/paged-data.ts @@ -3,7 +3,7 @@ import { Page } from './page'; /** * An array of data with an associated page object used for paging */ -export class PagedData { - data = new Array(); - page = new Page(); +export interface PagedData { + data: T[] + page: Page; } diff --git a/src/app/paging/paging-client.component.ts b/src/app/paging/paging-client.component.ts index 5f01d116e..d7e99bb28 100644 --- a/src/app/paging/paging-client.component.ts +++ b/src/app/paging/paging-client.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'client-paging-demo', @@ -31,7 +32,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class ClientPagingComponent { - rows = []; + rows: Employee[] = []; ColumnMode = ColumnMode; diff --git a/src/app/paging/paging-scrolling-novirtualization.component.ts b/src/app/paging/paging-scrolling-novirtualization.component.ts index f13a0cfb9..763d8ea64 100644 --- a/src/app/paging/paging-scrolling-novirtualization.component.ts +++ b/src/app/paging/paging-scrolling-novirtualization.component.ts @@ -1,8 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { MockServerResultsService } from './mock-server-results-service'; -import { CorporateEmployee } from './model/corporate-employee'; import { Page } from './model/page'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'paging-scrolling-novirtualization-demo', @@ -41,15 +41,17 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class PagingScrollingNoVirtualizationComponent implements OnInit{ - page = new Page(); - rows = new Array(); + page: Page = { + pageNumber: 0, + size: 20, + totalElements: 0, + totalPages: 0 + } + rows: Employee[] = []; ColumnMode = ColumnMode; - constructor(private serverResultsService: MockServerResultsService) { - this.page.pageNumber = 0; - this.page.size = 20; - } + constructor(private serverResultsService: MockServerResultsService) {} ngOnInit() { this.setPage({ offset: 0 }); diff --git a/src/app/paging/paging-server.component.ts b/src/app/paging/paging-server.component.ts index 89ace654d..47a830a90 100644 --- a/src/app/paging/paging-server.component.ts +++ b/src/app/paging/paging-server.component.ts @@ -1,8 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { MockServerResultsService } from './mock-server-results-service'; -import { CorporateEmployee } from './model/corporate-employee'; import { Page } from './model/page'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'server-paging-demo', @@ -39,15 +39,17 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class ServerPagingComponent implements OnInit{ - page = new Page(); - rows = new Array(); + page: Page = { + pageNumber: 0, + size: 20, + totalElements: 0, + totalPages: 0 + } + rows: Employee[] = [] ColumnMode = ColumnMode; - constructor(private serverResultsService: MockServerResultsService) { - this.page.pageNumber = 0; - this.page.size = 20; - } + constructor(private serverResultsService: MockServerResultsService) {} ngOnInit() { this.setPage({ offset: 0 }); diff --git a/src/app/paging/paging-virtual.component.ts b/src/app/paging/paging-virtual.component.ts index 91fa16a06..fd492ea94 100644 --- a/src/app/paging/paging-virtual.component.ts +++ b/src/app/paging/paging-virtual.component.ts @@ -1,9 +1,8 @@ import { Component } from '@angular/core'; import { MockServerResultsService } from './mock-server-results-service'; -import { CorporateEmployee } from './model/corporate-employee'; import { Page } from './model/page'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; -import { delay } from 'rxjs/operators'; +import { Employee } from "../data.model"; interface PageInfo { offset: number; @@ -58,8 +57,8 @@ interface PageInfo { export class VirtualPagingComponent { totalElements: number; pageNumber: number; - rows: CorporateEmployee[]; - cache: any = {}; + rows: Employee[]; + cache: Record = {}; cachePageSize = 0; ColumnMode = ColumnMode; @@ -81,9 +80,12 @@ export class VirtualPagingComponent { // This is the scroll position in rows const rowOffset = pageInfo.offset * pageInfo.pageSize; - const page = new Page(); - page.size = pageInfo.pageSize; - page.pageNumber = Math.floor(rowOffset / page.size); + const page: Page = { + pageNumber: Math.floor(rowOffset / pageInfo.pageSize), + size: pageInfo.pageSize, + totalElements: 0, + totalPages: 0 + } // We keep a index of server loaded pages so we don't load same data twice // This is based on the server page not the UI @@ -104,7 +106,7 @@ export class VirtualPagingComponent { // Create array to store data if missing // The array should have the correct number of with "holes" for missing data if (!this.rows) { - this.rows = new Array(this.totalElements || 0); + this.rows = new Array(this.totalElements || 0); } // Calc starting row offset diff --git a/src/app/paging/scrolling-server.component.ts b/src/app/paging/scrolling-server.component.ts index 643e0a6a1..5a0d27fc3 100644 --- a/src/app/paging/scrolling-server.component.ts +++ b/src/app/paging/scrolling-server.component.ts @@ -1,10 +1,11 @@ import { Component, ElementRef, Injectable, OnInit } from '@angular/core'; import { Observable, of } from 'rxjs'; import { delay, map } from 'rxjs/operators'; -import { CorporateEmployee } from './model/corporate-employee'; import data from 'src/assets/data/company.json'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; + const companyData = data as any[]; class PagedData { @@ -16,7 +17,7 @@ class PagedData { */ @Injectable() export class MockServerResultsService { - public getResults(offset: number, limit: number): Observable> { + public getResults(offset: number, limit: number): Observable> { return of(companyData.slice(offset, offset + limit)).pipe( delay(new Date(Date.now() + 500)), map(d => ({ data: d })) @@ -61,7 +62,7 @@ export class ServerScrollingComponent implements OnInit { readonly rowHeight = 50; readonly pageLimit = 10; - rows: CorporateEmployee[] = []; + rows: Employee[] = []; isLoading: boolean; ColumnMode = ColumnMode; diff --git a/src/app/selection/selection-cell.component.ts b/src/app/selection/selection-cell.component.ts index c007135ab..208330565 100644 --- a/src/app/selection/selection-cell.component.ts +++ b/src/app/selection/selection-cell.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode, SelectionType } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, SelectionType, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'cell-selection-demo', @@ -34,9 +35,9 @@ import { ColumnMode, SelectionType } from 'projects/ngx-datatable/src/public-api ` }) export class CellSelectionComponent { - rows: any[] = []; - selected: any[] = []; - columns: any[] = [{ prop: 'name' }, { name: 'Company' }, { name: 'Gender' }]; + rows: Employee[] = []; + selected: Employee[] = []; + columns: TableColumn[] = [{ prop: 'name' }, { name: 'Company' }, { name: 'Gender' }]; ColumnMode = ColumnMode; SelectionType = SelectionType; diff --git a/src/app/selection/selection-chkbox-template.component.ts b/src/app/selection/selection-chkbox-template.component.ts index 85a238e72..95299374a 100644 --- a/src/app/selection/selection-chkbox-template.component.ts +++ b/src/app/selection/selection-chkbox-template.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode, SelectionType } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'chkbox-selection-template-demo', @@ -45,11 +46,10 @@ import { ColumnMode, SelectionType } from 'projects/ngx-datatable/src/public-api > - + ; + @ViewChild('nameSummaryCell') nameSummaryCell: TemplateRef; - columns = []; + columns: TableColumn[] = []; ColumnMode = ColumnMode; diff --git a/src/app/summary/summary-row-inline-html.component.ts b/src/app/summary/summary-row-inline-html.component.ts index e0729a7ca..7e7554ce6 100644 --- a/src/app/summary/summary-row-inline-html.component.ts +++ b/src/app/summary/summary-row-inline-html.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'summary-row-inline-html', @@ -40,7 +41,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class SummaryRowInlineHtmlComponent { - rows = []; + rows: Employee[] = []; enableSummary = true; summaryPosition = 'top'; diff --git a/src/app/summary/summary-row-server-paging.component.ts b/src/app/summary/summary-row-server-paging.component.ts index 735cdfdca..456a99d54 100644 --- a/src/app/summary/summary-row-server-paging.component.ts +++ b/src/app/summary/summary-row-server-paging.component.ts @@ -1,9 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { MockServerResultsService } from '../paging/mock-server-results-service'; -import { PagedData } from '../paging/model/paged-data'; -import { CorporateEmployee } from '../paging/model/corporate-employee'; import { Page } from '../paging/model/page'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'summary-row-server-paging-demo', @@ -41,8 +40,13 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class SummaryRowServerPagingComponent implements OnInit { - page = new Page(); - rows = new Array(); + page: Page = { + pageNumber: 0, + size: 20, + totalPages: 0, + totalElements: 0 + } + rows: Employee[] = []; columns = [ // NOTE: cells for current page only ! @@ -53,10 +57,7 @@ export class SummaryRowServerPagingComponent implements OnInit { ColumnMode = ColumnMode; - constructor(private serverResultsService: MockServerResultsService) { - this.page.pageNumber = 0; - this.page.size = 20; - } + constructor(private serverResultsService: MockServerResultsService) {} ngOnInit() { this.setPage({ offset: 0 }); diff --git a/src/app/summary/summary-row-simple.component.ts b/src/app/summary/summary-row-simple.component.ts index 2440d57ab..e76cc6576 100644 --- a/src/app/summary/summary-row-simple.component.ts +++ b/src/app/summary/summary-row-simple.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'summary-row-simple-demo', @@ -50,9 +51,9 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; styleUrls: ['./summary-row-simple.component.scss'] }) export class SummaryRowSimpleComponent { - rows = []; + rows: Employee[] = []; - columns = [ + columns: TableColumn[] = [ { prop: 'name', summaryFunc: null }, { name: 'Gender', summaryFunc: cells => this.summaryForGender(cells) }, { prop: 'age', summaryFunc: cells => this.avgAge(cells) } @@ -69,7 +70,7 @@ export class SummaryRowSimpleComponent { }); } - fetch(cb: (data: [unknown]) => void) { + fetch(cb: (data: [Employee]) => void) { const req = new XMLHttpRequest(); req.open('GET', `assets/data/company.json`); diff --git a/src/app/templates/template-dom.component.ts b/src/app/templates/template-dom.component.ts index ccb13fd3e..b2eae5e41 100644 --- a/src/app/templates/template-dom.component.ts +++ b/src/app/templates/template-dom.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'inline-templates-demo', @@ -51,7 +52,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; ` }) export class InlineTemplatesComponent { - rows = []; + rows: Employee[] = []; joke = 'knock knock'; ColumnMode = ColumnMode; diff --git a/src/app/templates/template-obj.component.ts b/src/app/templates/template-obj.component.ts index 9822d9f3d..f33e28200 100644 --- a/src/app/templates/template-obj.component.ts +++ b/src/app/templates/template-obj.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TableColumn } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'template-ref-demo', @@ -40,8 +41,8 @@ export class TemplateRefTemplatesComponent implements OnInit { @ViewChild('editTmpl', { static: true }) editTmpl: TemplateRef; @ViewChild('hdrTpl', { static: true }) hdrTpl: TemplateRef; - rows = []; - columns = []; + rows: Employee[] = []; + columns: TableColumn[] = []; ColumnMode = ColumnMode; diff --git a/src/app/tree/client-tree.component.ts b/src/app/tree/client-tree.component.ts index 0ec654032..9c6e8f2c4 100644 --- a/src/app/tree/client-tree.component.ts +++ b/src/app/tree/client-tree.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TreeStatus } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'client-side-tree-demo', @@ -48,7 +49,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; styles: ['.icon {height: 10px; width: 10px; }', '.disabled {opacity: 0.5; }'] }) export class ClientTreeComponent { - rows = []; + rows: (Employee & {treeStatus: TreeStatus})[] = []; ColumnMode = ColumnMode; diff --git a/src/app/tree/fullscreen.component.ts b/src/app/tree/fullscreen.component.ts index 1bd61743c..6d66126b9 100644 --- a/src/app/tree/fullscreen.component.ts +++ b/src/app/tree/fullscreen.component.ts @@ -1,5 +1,6 @@ import { ChangeDetectorRef, Component } from '@angular/core'; -import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; +import { ColumnMode, TreeStatus } from 'projects/ngx-datatable/src/public-api'; +import { Employee } from "../data.model"; @Component({ selector: 'full-screen-tree-demo', @@ -59,7 +60,7 @@ import { ColumnMode } from 'projects/ngx-datatable/src/public-api'; styles: ['.icon {height: 10px; width: 10px; }', '.disabled {opacity: 0.5; }'] }) export class FullScreenTreeComponent { - rows = []; + rows: (Employee & {treeStatus: TreeStatus})[] = []; lastIndex = 15; ColumnMode = ColumnMode;