UNPKG

@ngx-custom-code/ngx-table-custom-sort

Version:

Angular easy table

1 lines 129 kB
{"version":3,"file":"ngx-custom-code-ngx-table-custom-sort.mjs","sources":["../../../projects/ngx-easy-table/src/lib/model/config.ts","../../../projects/ngx-easy-table/src/lib/model/event.enum.ts","../../../projects/ngx-easy-table/src/lib/model/api.ts","../../../projects/ngx-easy-table/src/lib/services/config-service.ts","../../../projects/ngx-easy-table/src/lib/services/group-rows.service.ts","../../../projects/ngx-easy-table/src/lib/services/style.service.ts","../../../projects/ngx-easy-table/src/lib/components/pagination/pagination.component.ts","../../../projects/ngx-easy-table/src/lib/components/pagination/pagination.html","../../../projects/ngx-easy-table/src/lib/components/header/header.component.ts","../../../projects/ngx-easy-table/src/lib/components/header/header.html","../../../projects/ngx-easy-table/src/lib/components/thead/thead.component.ts","../../../projects/ngx-easy-table/src/lib/components/thead/thead.component.html","../../../projects/ngx-easy-table/src/lib/services/filters.service.ts","../../../projects/ngx-easy-table/src/lib/pipes/search-pipe.ts","../../../projects/ngx-easy-table/src/lib/pipes/render-pipe.ts","../../../projects/ngx-easy-table/src/lib/pipes/global-search-pipe.ts","../../../projects/ngx-easy-table/src/lib/pipes/sort.pipe.ts","../../../projects/ngx-easy-table/src/lib/components/base/base.component.ts","../../../projects/ngx-easy-table/src/lib/components/base/base.component.html","../../../projects/ngx-easy-table/src/lib/components/base/base.module.ts","../../../projects/ngx-easy-table/src/lib/table.module.ts","../../../projects/ngx-easy-table/src/ngx-custom-code-ngx-table-custom-sort.ts"],"sourcesContent":["export interface Config {\r\n searchEnabled: boolean;\r\n /* @deprecated Will be removed in the next version */\r\n headerEnabled: boolean;\r\n orderEnabled: boolean;\r\n orderEventOnly?: boolean;\r\n paginationEnabled: boolean;\r\n clickEvent: boolean;\r\n selectRow: boolean;\r\n selectCol: boolean;\r\n selectCell: boolean;\r\n rows: number;\r\n additionalActions: boolean;\r\n serverPagination: boolean;\r\n isLoading: boolean;\r\n detailsTemplate: boolean;\r\n /* @deprecated Will be removed in the next version */\r\n groupRows: boolean;\r\n paginationRangeEnabled: boolean;\r\n collapseAllRows: boolean;\r\n checkboxes: boolean;\r\n radio?: boolean;\r\n resizeColumn: boolean;\r\n fixedColumnWidth: boolean;\r\n horizontalScroll: boolean;\r\n logger: boolean;\r\n showDetailsArrow?: boolean;\r\n showContextMenu?: boolean;\r\n persistState?: boolean;\r\n /* @deprecated Will be removed in the next version */\r\n paginationMaxSize?: number;\r\n threeWaySort?: boolean;\r\n columnReorder?: boolean;\r\n /* @deprecated Will be removed in the next version */\r\n rowReorder?: boolean;\r\n reorderDelay?: number;\r\n infiniteScroll?: boolean;\r\n infiniteScrollThrottleTime?: number;\r\n onDragOver?: boolean;\r\n tableLayout: {\r\n style: STYLE | string | null;\r\n theme: THEME | string | null;\r\n borderless: boolean | null;\r\n hover: boolean | null;\r\n striped: boolean | null;\r\n };\r\n}\r\n\r\nexport enum STYLE {\r\n TINY = 'tiny',\r\n BIG = 'big',\r\n NORMAL = 'normal',\r\n}\r\n\r\nexport enum THEME {\r\n LIGHT = 'light',\r\n DARK = 'dark',\r\n}\r\n","export enum Event {\r\n onPagination = 'onPagination',\r\n onOrder = 'onOrder',\r\n onGlobalSearch = 'onGlobalSearch',\r\n onSearch = 'onSearch',\r\n onClick = 'onClick',\r\n onDoubleClick = 'onDoubleClick',\r\n onCheckboxSelect = 'onCheckboxSelect',\r\n onRadioSelect = 'onRadioSelect',\r\n onCheckboxToggle = 'onCheckboxToggle',\r\n onSelectAll = 'onSelectAll',\r\n onInfiniteScrollEnd = 'onInfiniteScrollEnd',\r\n onColumnResizeMouseDown = 'onColumnResizeMouseDown',\r\n onColumnResizeMouseUp = 'onColumnResizeMouseUp',\r\n /* @deprecated Will be removed in the next version */\r\n onRowDrop = 'onRowDrop',\r\n /* @deprecated Will be removed in the next version */\r\n onReorderStart = 'onReorderStart',\r\n onRowCollapsedShow = 'onRowCollapsedShow',\r\n onRowCollapsedHide = 'onRowCollapsedHide',\r\n onRowContextMenu = 'onRowContextMenu',\r\n}\r\n","export enum API {\r\n rowContextMenuClicked = 'rowContextMenuClicked',\r\n setInputValue = 'setInputValue',\r\n toggleRowIndex = 'toggleRowIndex',\r\n toggleCheckbox = 'toggleCheckbox',\r\n onGlobalSearch = 'onGlobalSearch',\r\n setPaginationCurrentPage = 'setPaginationCurrentPage',\r\n getPaginationCurrentPage = 'getPaginationCurrentPage',\r\n getPaginationTotalItems = 'getPaginationTotalItems',\r\n getNumberOfRowsPerPage = 'getNumberOfRowsPerPage',\r\n getPaginationLastPage = 'getPaginationLastPage',\r\n setPaginationRange = 'setPaginationRange',\r\n setPaginationPreviousLabel = 'setPaginationPreviousLabel',\r\n setPaginationNextLabel = 'setPaginationNextLabel',\r\n setPaginationDisplayLimit = 'setPaginationDisplayLimit',\r\n setTableClass = 'setTableClass',\r\n setRowClass = 'setRowClass',\r\n setCellClass = 'setCellClass',\r\n setRowStyle = 'setRowStyle',\r\n setCellStyle = 'setCellStyle',\r\n sortBy = 'sortBy',\r\n}\r\n\r\nexport interface RowClass {\r\n row: number;\r\n className: string;\r\n}\r\nexport interface CellClass {\r\n row: number;\r\n cell: number | string;\r\n className: string;\r\n}\r\nexport interface RowStyle {\r\n row: number;\r\n attr: string;\r\n value: string;\r\n}\r\nexport interface CellStyle {\r\n row: number;\r\n cell: number;\r\n attr: string;\r\n value: string;\r\n}\r\n\r\nexport type ApiType =\r\n | { type: API.rowContextMenuClicked }\r\n | { type: API.setInputValue; value: Array<{ key: string; value: string }> }\r\n | { type: API.toggleRowIndex; value: number }\r\n | { type: API.toggleCheckbox; value: number }\r\n | { type: API.onGlobalSearch; value: string }\r\n | { type: API.setPaginationCurrentPage; value: number }\r\n | { type: API.getPaginationCurrentPage }\r\n | { type: API.getPaginationTotalItems }\r\n | { type: API.getPaginationLastPage }\r\n | { type: API.getNumberOfRowsPerPage }\r\n | { type: API.setPaginationRange; value: number[] }\r\n | { type: API.setPaginationPreviousLabel; value: string }\r\n | { type: API.setPaginationNextLabel; value: string }\r\n | { type: API.setPaginationDisplayLimit; value: number }\r\n | { type: API.setTableClass; value: string | null }\r\n | { type: API.setRowClass; value: RowClass | RowClass[] }\r\n | { type: API.setCellClass; value: CellClass | CellClass[] }\r\n | { type: API.setRowStyle; value: RowStyle | RowStyle[] }\r\n | { type: API.setCellStyle; value: CellStyle | CellStyle[] }\r\n | { type: API.sortBy; value: { column: string; order: 'asc' | 'desc' } };\r\n\r\nexport interface APIDefinition {\r\n apiEvent<B extends ApiType>(event: B): IAPIDefinition<B>;\r\n}\r\n\r\nexport type IAPIDefinition<B> = B extends\r\n | { type: API.getPaginationCurrentPage }\r\n | { type: API.getPaginationTotalItems }\r\n | { type: API.getPaginationLastPage }\r\n | { type: API.getNumberOfRowsPerPage }\r\n ? number\r\n : void;\r\n","import { Injectable } from '@angular/core';\r\nimport { Config, STYLE, THEME } from '../model/config';\r\n\r\n// eslint-disable-next-line, no-underscore-dangle, id-blacklist, id-match\r\nexport const DefaultConfig: Config = {\r\n searchEnabled: false,\r\n headerEnabled: true,\r\n orderEnabled: true,\r\n orderEventOnly: false,\r\n paginationEnabled: true,\r\n clickEvent: true,\r\n selectRow: false,\r\n selectCol: false,\r\n selectCell: false,\r\n rows: 10,\r\n additionalActions: false,\r\n serverPagination: false,\r\n isLoading: false,\r\n detailsTemplate: false,\r\n groupRows: false,\r\n paginationRangeEnabled: true,\r\n collapseAllRows: false,\r\n checkboxes: false,\r\n radio: false,\r\n resizeColumn: false,\r\n fixedColumnWidth: true,\r\n horizontalScroll: false,\r\n logger: false,\r\n showDetailsArrow: false,\r\n showContextMenu: false,\r\n persistState: false,\r\n paginationMaxSize: 5,\r\n threeWaySort: false,\r\n onDragOver: false,\r\n tableLayout: {\r\n style: STYLE.NORMAL,\r\n theme: THEME.LIGHT,\r\n borderless: false,\r\n hover: true,\r\n striped: false,\r\n },\r\n};\r\n\r\n@Injectable()\r\nexport class DefaultConfigService {\r\n public static config: Config = DefaultConfig;\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { from } from 'rxjs';\r\nimport { mergeMap, groupBy, reduce } from 'rxjs/operators';\r\n\r\n@Injectable()\r\nexport class GroupRowsService {\r\n public static doGroupRows<T>(data: T[], groupRowsBy: string): any[] {\r\n const grouped: any[] = [];\r\n from(data)\r\n .pipe(\r\n groupBy((row) => row[groupRowsBy]),\r\n mergeMap((group) => group.pipe(reduce((acc: T[], curr: T) => [...acc, curr], [])))\r\n )\r\n .subscribe((row) => grouped.push(row));\r\n\r\n return grouped;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { CellClass, CellStyle, RowClass, RowStyle } from '..';\r\n\r\n/* eslint-disable */\r\n@Injectable()\r\nexport class StyleService {\r\n public setRowClass(val: RowClass): void {\r\n const selector = `#table > tbody > tr:nth-child(${val.row})`;\r\n const row = document.querySelector(selector) as HTMLTableRowElement;\r\n if (row) {\r\n row.classList.add(val.className);\r\n }\r\n }\r\n\r\n public setCellClass(val: CellClass): void {\r\n const selector = `#table > tbody > tr:nth-child(${val.row}) > td:nth-child(${val.cell})`;\r\n const cell = document.querySelector(selector) as HTMLTableCellElement;\r\n if (cell) {\r\n cell.classList.add(val.className);\r\n }\r\n }\r\n\r\n public setRowStyle(val: RowStyle): void {\r\n const selector = `#table > tbody > tr:nth-child(${val.row})`;\r\n const row = document.querySelector(selector) as HTMLTableRowElement;\r\n if (row) {\r\n // eslint-disable-next-line @typescript-eslint/dot-notation\r\n row.style[val.attr] = val.value;\r\n }\r\n }\r\n\r\n public setCellStyle(val: CellStyle): void {\r\n const selector = `#table > tbody > tr:nth-child(${val.row}) > td:nth-child(${val.cell})`;\r\n const cell = document.querySelector(selector) as HTMLTableCellElement;\r\n if (cell) {\r\n // eslint-disable-next-line @typescript-eslint/dot-notation\r\n cell.style[val.attr] = val.value;\r\n }\r\n }\r\n\r\n public pinnedWidth(pinned: boolean | undefined, column: number): string | undefined {\r\n if (pinned) {\r\n return 150 * column + 'px';\r\n }\r\n }\r\n}\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n EventEmitter,\r\n HostListener,\r\n Input,\r\n OnChanges,\r\n Output,\r\n SimpleChanges,\r\n ViewChild,\r\n} from '@angular/core';\r\nimport { Config } from '../..';\r\nimport { PaginationControlsDirective } from 'ngx-pagination';\r\n\r\nexport interface PaginationRange {\r\n page: number;\r\n limit: number;\r\n}\r\n\r\n@Component({\r\n selector: 'pagination',\r\n templateUrl: './pagination.html',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class PaginationComponent implements OnChanges {\r\n @ViewChild('paginationDirective')\r\n paginationDirective: PaginationControlsDirective;\r\n @ViewChild('paginationRange') paginationRange;\r\n @Input() pagination;\r\n @Input() config: Config;\r\n @Input() id;\r\n @Output() readonly updateRange: EventEmitter<PaginationRange> = new EventEmitter();\r\n public ranges: number[] = [5, 10, 25, 50, 100];\r\n public selectedLimit: number;\r\n public showRange = false;\r\n public screenReaderPaginationLabel = 'Pagination';\r\n public screenReaderPageLabel = 'page';\r\n public screenReaderCurrentLabel = 'You are on page';\r\n public previousLabel = '';\r\n public nextLabel = '';\r\n public directionLinks = true;\r\n\r\n @HostListener('document:click', ['$event.target'])\r\n public onClick(targetElement: any): void {\r\n if (this.paginationRange && !this.paginationRange.nativeElement.contains(targetElement)) {\r\n this.showRange = false;\r\n }\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n const { config } = changes;\r\n if (config && config.currentValue) {\r\n this.selectedLimit = this.config.rows;\r\n }\r\n }\r\n\r\n onPageChange(page: number): void {\r\n this.updateRange.emit({\r\n page,\r\n limit: this.selectedLimit,\r\n });\r\n }\r\n\r\n changeLimit(limit: number, callFromAPI: boolean): void {\r\n if (!callFromAPI) {\r\n this.showRange = !this.showRange;\r\n }\r\n this.selectedLimit = limit;\r\n this.updateRange.emit({\r\n page: 1,\r\n limit,\r\n });\r\n }\r\n}\r\n","<div\r\n class=\"ngx-pagination-wrapper\"\r\n [style.display]=\"config.paginationEnabled ? '' : 'none'\"\r\n [class.ngx-table__table--dark-pagination-wrapper]=\"config.tableLayout.theme === 'dark'\"\r\n>\r\n <div class=\"ngx-pagination-steps\">\r\n <pagination-template\r\n #paginationDirective=\"paginationApi\"\r\n id=\"pagination-controls\"\r\n [id]=\"id\"\r\n [class.ngx-table__table--dark-pagination]=\"config.tableLayout.theme === 'dark'\"\r\n [maxSize]=\"config.paginationMaxSize || 5\"\r\n (pageChange)=\"onPageChange($event)\"\r\n >\r\n <ul\r\n class=\"ngx-pagination\"\r\n role=\"navigation\"\r\n [attr.aria-label]=\"screenReaderPaginationLabel\"\r\n [class.responsive]=\"true\"\r\n >\r\n <li\r\n class=\"pagination-previous\"\r\n [class.disabled]=\"paginationDirective.isFirstPage()\"\r\n *ngIf=\"directionLinks\"\r\n >\r\n <a\r\n tabindex=\"0\"\r\n *ngIf=\"1 < paginationDirective.getCurrent()\"\r\n (keyup.enter)=\"paginationDirective.previous()\"\r\n (click)=\"paginationDirective.previous()\"\r\n [attr.aria-label]=\"previousLabel + ' ' + screenReaderPageLabel\"\r\n >\r\n {{ previousLabel }} <span class=\"show-for-sr\">{{ screenReaderPageLabel }}</span>\r\n </a>\r\n <span *ngIf=\"paginationDirective.isFirstPage()\">\r\n {{ previousLabel }} <span class=\"show-for-sr\">{{ screenReaderPageLabel }}</span>\r\n </span>\r\n </li>\r\n <li class=\"small-screen\">\r\n {{ paginationDirective.getCurrent() }} / {{ paginationDirective.getLastPage() }}\r\n </li>\r\n <li\r\n [class.current]=\"paginationDirective.getCurrent() === page.value\"\r\n [class.ellipsis]=\"page.label === '...'\"\r\n *ngFor=\"let page of paginationDirective.pages\"\r\n >\r\n <a\r\n tabindex=\"0\"\r\n (keyup.enter)=\"paginationDirective.setCurrent(page.value)\"\r\n (click)=\"paginationDirective.setCurrent(page.value)\"\r\n *ngIf=\"paginationDirective.getCurrent() !== page.value\"\r\n >\r\n <span class=\"show-for-sr\">{{ screenReaderPageLabel }} </span>\r\n <span>{{ page.label }}</span>\r\n </a>\r\n <ng-container *ngIf=\"paginationDirective.getCurrent() === page.value\">\r\n <span class=\"show-for-sr\">{{ screenReaderCurrentLabel }} </span>\r\n <span>{{ page.label }}</span>\r\n </ng-container>\r\n </li>\r\n <li\r\n class=\"pagination-next\"\r\n [class.disabled]=\"paginationDirective.isLastPage()\"\r\n *ngIf=\"directionLinks\"\r\n >\r\n <a\r\n tabindex=\"0\"\r\n *ngIf=\"!paginationDirective.isLastPage()\"\r\n (keyup.enter)=\"paginationDirective.next()\"\r\n (click)=\"paginationDirective.next()\"\r\n [attr.aria-label]=\"nextLabel + ' ' + screenReaderPageLabel\"\r\n >\r\n {{ nextLabel }} <span class=\"show-for-sr\">{{ screenReaderPageLabel }}</span>\r\n </a>\r\n <span *ngIf=\"paginationDirective.isLastPage()\">\r\n {{ nextLabel }} <span class=\"show-for-sr\">{{ screenReaderPageLabel }}</span>\r\n </span>\r\n </li>\r\n </ul>\r\n </pagination-template>\r\n </div>\r\n <div\r\n class=\"ngx-pagination-range\"\r\n #paginationRange\r\n [class.ngx-table__table--dark-pagination-range]=\"config.tableLayout.theme === 'dark'\"\r\n *ngIf=\"config.paginationRangeEnabled\"\r\n >\r\n <div class=\"ngx-dropdown ngx-pagination-range-dropdown\" id=\"rowAmount\">\r\n <div class=\"ngx-btn-group\">\r\n <div class=\"ngx-pagination-range-dropdown-button\" (click)=\"showRange = !showRange\">\r\n {{selectedLimit}} <i class=\"ngx-icon ngx-icon-arrow-down\"></i>\r\n </div>\r\n <ul class=\"ngx-menu\" *ngIf=\"showRange\">\r\n <li\r\n class=\"ngx-pagination-range-dropdown-button-item\"\r\n [class.ngx-pagination-range--selected]=\"limit === selectedLimit\"\r\n (click)=\"changeLimit(limit, false)\"\r\n *ngFor=\"let limit of ranges\"\r\n >\r\n <span>{{limit}}</span>\r\n </li>\r\n </ul>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n","import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';\r\nimport { Columns } from '../..';\r\n\r\n@Component({\r\n selector: 'table-header',\r\n templateUrl: './header.html',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class HeaderComponent {\r\n @Input() column: Columns;\r\n @Output() readonly update = new EventEmitter<Array<{ key: string; value: string }>>();\r\n\r\n unifyKey(key: string): string {\r\n return key.replace('.', '_');\r\n }\r\n\r\n onSearch(input: HTMLInputElement): void {\r\n this.update.emit([{ value: input.value, key: this.column.key }]);\r\n }\r\n}\r\n","<label for=\"search_{{ unifyKey(column.key) }}\">\r\n <input\r\n type=\"text\"\r\n id=\"search_{{ unifyKey(column.key) }}\"\r\n aria-label=\"Search\"\r\n placeholder=\"{{ column.placeholder ? column.placeholder : column.title }}\"\r\n class=\"ngx-table__header-search\"\r\n #input\r\n (input)=\"onSearch(input)\"\r\n />\r\n</label>\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n EventEmitter,\r\n HostListener,\r\n Input,\r\n Output,\r\n TemplateRef,\r\n ViewChild,\r\n ViewChildren,\r\n} from '@angular/core';\r\nimport { Columns, Config, Event } from '../..';\r\nimport { StyleService } from '../../services/style.service';\r\nimport { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';\r\n\r\n@Component({\r\n selector: '[table-thead]',\r\n templateUrl: './thead.component.html',\r\n styles: [\r\n `\r\n .cdk-drag-preview {\r\n text-align: left;\r\n padding-top: 9px;\r\n padding-left: 4px;\r\n color: #50596c;\r\n border: 1px solid #e7e9ed;\r\n }\r\n `,\r\n ],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n providers: [StyleService],\r\n})\r\nexport class TableTHeadComponent {\r\n public menuActive = false;\r\n public openedHeaderActionTemplate: string | null = null;\r\n public startOffset;\r\n public onSelectAllBinded = this.onSelectAll.bind(this);\r\n\r\n @Input() config: Config;\r\n @Input() columns: Columns[];\r\n @Input() sortKey;\r\n @Input() sortState;\r\n @Input() selectAllTemplate;\r\n @Input() filtersTemplate;\r\n @Input() additionalActionsTemplate: TemplateRef<void>;\r\n @Input() isAllSortEnabled: boolean = true;\r\n @Output() readonly filter = new EventEmitter<Array<{ key: string; value: string }>>();\r\n @Output() readonly order = new EventEmitter<Columns>();\r\n @Output() readonly selectAll = new EventEmitter<void>();\r\n @Output() readonly event = new EventEmitter<{ event: string; value: any }>();\r\n @ViewChild('th') private th;\r\n @ViewChildren('headerDropdown') headerDropdown;\r\n @ViewChild('additionalActionMenu') additionalActionMenu;\r\n @HostListener('document:click', ['$event.target'])\r\n public onClick(targetElement: any): void {\r\n if (\r\n this.additionalActionMenu &&\r\n !this.additionalActionMenu.nativeElement.contains(targetElement)\r\n ) {\r\n this.menuActive = false;\r\n }\r\n\r\n // if click outside the header then close opened Header Action Template\r\n if (\r\n this.openedHeaderActionTemplate &&\r\n // if no header have the clicked point\r\n !this.headerDropdown.toArray().some((ref) => ref.nativeElement.contains(targetElement))\r\n ) {\r\n this.openedHeaderActionTemplate = null;\r\n }\r\n }\r\n\r\n constructor(public readonly styleService: StyleService) {\r\n }\r\n\r\n getColumnDefinition(column: Columns): boolean {\r\n return column.searchEnabled || typeof column.searchEnabled === 'undefined';\r\n }\r\n\r\n orderBy(column: Columns): void {\r\n this.order.emit(column);\r\n }\r\n\r\n isOrderEnabled(column: Columns): boolean {\r\n const columnOrderEnabled = column.orderEnabled === undefined ? true : !!column.orderEnabled;\r\n return this.config.orderEnabled && columnOrderEnabled;\r\n }\r\n\r\n columnDrop(event: CdkDragDrop<string[]>): void {\r\n moveItemInArray(this.columns, event.previousIndex, event.currentIndex);\r\n }\r\n\r\n onSearch($event: Array<{ key: string; value: string }>): void {\r\n this.filter.emit($event);\r\n }\r\n\r\n getColumnWidth(column: any): string | null {\r\n if (column.width) {\r\n return column.width;\r\n }\r\n return this.config.fixedColumnWidth ? 100 / this.columns.length + '%' : null;\r\n }\r\n\r\n onSelectAll(): void {\r\n this.selectAll.emit();\r\n }\r\n\r\n onMouseDown(event: MouseEvent, th: HTMLTableHeaderCellElement): void {\r\n if (!this.config.resizeColumn) {\r\n return;\r\n }\r\n this.th = th;\r\n this.startOffset = th.offsetWidth - event.pageX;\r\n this.event.emit({\r\n event: Event.onColumnResizeMouseDown,\r\n value: event,\r\n });\r\n }\r\n\r\n onMouseMove(event: MouseEvent): void {\r\n if (!this.config.resizeColumn) {\r\n return;\r\n }\r\n if (this.th && this.th.style) {\r\n this.th.style.width = this.startOffset + event.pageX + 'px';\r\n this.th.style.cursor = 'col-resize';\r\n this.th.style['user-select'] = 'none';\r\n }\r\n }\r\n\r\n onMouseUp(event: MouseEvent): void {\r\n if (!this.config.resizeColumn) {\r\n return;\r\n }\r\n this.event.emit({\r\n event: Event.onColumnResizeMouseUp,\r\n value: event,\r\n });\r\n this.th.style.cursor = 'default';\r\n this.th = undefined;\r\n }\r\n\r\n showHeaderActionTemplateMenu(column: Columns): void {\r\n if (!column.headerActionTemplate) {\r\n console.error('Column [headerActionTemplate] property not defined');\r\n }\r\n if (this.openedHeaderActionTemplate === column.key) {\r\n this.openedHeaderActionTemplate = null;\r\n return;\r\n }\r\n this.openedHeaderActionTemplate = column.key;\r\n }\r\n\r\n showMenu(): void {\r\n if (!this.additionalActionsTemplate) {\r\n console.error('[additionalActionsTemplate] property not defined');\r\n }\r\n this.menuActive = !this.menuActive;\r\n }\r\n}\r\n","<tr class=\"ngx-table__header\" *ngIf=\"config.headerEnabled && !config.columnReorder\">\r\n <th *ngIf=\"config.checkboxes || config.radio\" [style.width]=\"'3%'\">\r\n <ng-container\r\n *ngIf=\"selectAllTemplate && config.checkboxes\"\r\n [ngTemplateOutlet]=\"selectAllTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: onSelectAllBinded }\"\r\n >\r\n </ng-container>\r\n <label\r\n class=\"ngx-form-checkbox\"\r\n for=\"selectAllCheckboxes\"\r\n *ngIf=\"!selectAllTemplate && config.checkboxes\"\r\n >\r\n <input type=\"checkbox\" id=\"selectAllCheckboxes\" (change)=\"onSelectAll()\" />\r\n <em class=\"ngx-form-icon\" id=\"selectAllCheckbox\"></em>\r\n </label>\r\n </th>\r\n <ng-container *ngFor=\"let column of columns; let colIndex = index; let last = last\">\r\n <th\r\n class=\"ngx-table__header-cell\"\r\n [class.pinned-left]=\"column.pinned\"\r\n [ngClass]=\"column.cssClass && column.cssClass.includeHeader ? column.cssClass.name : ''\"\r\n [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\r\n #th\r\n [style.width]=\"getColumnWidth(column)\"\r\n (mousedown)=\"onMouseDown($event, th)\"\r\n (mouseup)=\"onMouseUp($event)\"\r\n (mousemove)=\"onMouseMove($event)\"\r\n >\r\n <div\r\n (click)=\"orderBy(column)\"\r\n style=\"display: inline\"\r\n [class.pointer]=\"isOrderEnabled(column)\"\r\n >\r\n <div class=\"ngx-table__header-title\">\r\n {{ column.title }}<span>&nbsp;</span>\r\n <em class=\"ngx-icon ngx-icon-pin\" *ngIf=\"column.pinned\"></em>\r\n <div [style.display]=\"config.orderEnabled ? 'inline' : 'none'\">\r\n <svg\r\n *ngIf=\"(column.isAllSortEnabled ?? true) && sortKey !== column.key && column.key !== ''\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 20 20\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <!-- Down arrow -->\r\n <path\r\n d=\"M10 17.4987L6.25 13.7487L7.45833 12.5404L10 15.082L12.5417 12.5404L13.75 13.7487L10 17.4987Z\"\r\n fill=\"#8486B9\"\r\n />\r\n <!-- Up arrow -->\r\n <path\r\n d=\"M7.45833 7.54036L6.25 6.33203L10 2.58203L13.75 6.33203L12.5417 7.54036L10 4.9987L7.45833 7.54036Z\"\r\n fill=\"#8486B9\"\r\n />\r\n </svg>\r\n \r\n \r\n <svg\r\n *ngIf=\"sortKey === column.key\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 20 20\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <!-- Down arrow -->\r\n <path\r\n d=\"M10 17.4987L6.25 13.7487L7.45833 12.5404L10 15.082L12.5417 12.5404L13.75 13.7487L10 17.4987Z\"\r\n [attr.fill]=\"sortState.get(sortKey) === 'asc' ? '#FCFCFF' : '#8486B9'\"\r\n />\r\n <!-- Up arrow -->\r\n <path\r\n d=\"M7.45833 7.54036L6.25 6.33203L10 2.58203L13.75 6.33203L12.5417 7.54036L10 4.9987L7.45833 7.54036Z\"\r\n [attr.fill]=\"sortState.get(sortKey) === 'desc' ? '#FCFCFF' : '#8486B9'\"\r\n />\r\n </svg>\r\n \r\n\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"ngx-dropdown\" *ngIf=\"!!column.headerActionTemplate\" #headerDropdown>\r\n <a class=\"ngx-btn ngx-btn-link\" (click)=\"showHeaderActionTemplateMenu(column)\">\r\n <span class=\"ngx-icon ngx-icon-more\"></span>\r\n </a>\r\n <div\r\n class=\"ngx-menu ngx-table__table-menu\"\r\n *ngIf=\"column.key === openedHeaderActionTemplate\"\r\n >\r\n <ng-container [ngTemplateOutlet]=\"column.headerActionTemplate\"> </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"ngx-table__column-resizer\" *ngIf=\"config.resizeColumn && !last\"></div>\r\n </th>\r\n </ng-container>\r\n <th\r\n *ngIf=\"\r\n config.additionalActions ||\r\n config.detailsTemplate ||\r\n config.collapseAllRows ||\r\n config.groupRows\r\n \"\r\n class=\"ngx-table__header-cell-additional-actions\"\r\n >\r\n <div class=\"ngx-dropdown\" #additionalActionMenu *ngIf=\"config.additionalActions\">\r\n <a class=\"ngx-btn ngx-btn-link\" (click)=\"showMenu()\">\r\n <span class=\"ngx-icon ngx-icon-menu\"></span>\r\n </a>\r\n <ul class=\"ngx-menu ngx-table__table-menu\" *ngIf=\"menuActive\">\r\n <ng-container\r\n *ngIf=\"additionalActionsTemplate\"\r\n [ngTemplateOutlet]=\"additionalActionsTemplate\"\r\n >\r\n </ng-container>\r\n </ul>\r\n </div>\r\n </th>\r\n</tr>\r\n<tr\r\n class=\"ngx-table__header ngx-table__header--draggable\"\r\n *ngIf=\"config.headerEnabled && config.columnReorder\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"columnDrop($event)\"\r\n>\r\n <th *ngIf=\"config.checkboxes || config.radio\" [style.width]=\"'3%'\">\r\n <ng-container\r\n *ngIf=\"selectAllTemplate && config.checkboxes\"\r\n [ngTemplateOutlet]=\"selectAllTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: onSelectAllBinded }\"\r\n >\r\n </ng-container>\r\n <label\r\n class=\"ngx-form-checkbox\"\r\n for=\"selectAllCheckboxes\"\r\n *ngIf=\"!selectAllTemplate && config.checkboxes\"\r\n >\r\n <input type=\"checkbox\" id=\"selectAllCheckboxesDrag\" (change)=\"onSelectAll()\" />\r\n <em class=\"ngx-form-icon\" id=\"selectAllCheckboxDrag\"></em>\r\n </label>\r\n </th>\r\n <ng-container *ngFor=\"let column of columns; let colIndex = index; let last = last\">\r\n <th\r\n class=\"ngx-table__header-cell ngx-table__header-cell--draggable\"\r\n cdkDragLockAxis=\"x\"\r\n cdkDrag\r\n [cdkDragStartDelay]=\"config.reorderDelay || 0\"\r\n [class.pinned-left]=\"column.pinned\"\r\n [ngClass]=\"column.cssClass && column.cssClass.includeHeader ? column.cssClass.name : ''\"\r\n [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\r\n #th\r\n [style.width]=\"getColumnWidth(column)\"\r\n (mousedown)=\"onMouseDown($event, th)\"\r\n (mouseup)=\"onMouseUp($event)\"\r\n (mousemove)=\"onMouseMove($event)\"\r\n >\r\n <div\r\n (click)=\"orderBy(column)\"\r\n style=\"display: inline\"\r\n cdkDragHandle\r\n [class.pointer]=\"isOrderEnabled(column)\"\r\n >\r\n <div class=\"ngx-table__header-title\">\r\n {{ column.title }}<span>&nbsp;</span>\r\n <em class=\"ngx-icon ngx-icon-pin\" *ngIf=\"column.pinned\"></em>\r\n <!-- <div [style.display]=\"isAllSortEnabled ||config.orderEnabled ? 'inline' : 'none'\">\r\n <em\r\n *ngIf=\"isAllSortEnabled\"\r\n class=\"ngx-icon ngx-icon-arrow-down\"\r\n >\r\n </em>\r\n <em\r\n *ngIf=\"sortKey === column.key && this.sortState.get(sortKey) === 'asc'\"\r\n class=\"ngx-icon ngx-icon-arrow-up\"\r\n >\r\n </em>\r\n <em\r\n *ngIf=\"sortKey === column.key && this.sortState.get(sortKey) === 'desc'\"\r\n class=\"ngx-icon ngx-icon-arrow-down\"\r\n >\r\n </em>\r\n </div> -->\r\n<div [style.display]=\"config.orderEnabled ? 'inline' : 'none'\">\r\n <svg\r\n *ngIf=\"sortKey === column.key\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 20 20\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n>\r\n <!-- Down arrow -->\r\n <path\r\n d=\"M10 17.4987L6.25 13.7487L7.45833 12.5404L10 15.082L12.5417 12.5404L13.75 13.7487L10 17.4987Z\"\r\n [attr.fill]=\"sortState.get(sortKey) === 'asc' ? '#FCFCFF' : '#8486B9'\"\r\n />\r\n <!-- Up arrow -->\r\n <path\r\n d=\"M7.45833 7.54036L6.25 6.33203L10 2.58203L13.75 6.33203L12.5417 7.54036L10 4.9987L7.45833 7.54036Z\"\r\n [attr.fill]=\"sortState.get(sortKey) === 'desc' ? '#FCFCFF' : '#8486B9'\"\r\n />\r\n</svg>\r\n\r\n\r\n\r\n<svg\r\n *ngIf=\"(column.isAllSortEnabled ?? true) && sortKey !== column.key && column.key !== ''\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 20 20\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n>\r\n <!-- Down arrow -->\r\n <path\r\n d=\"M10 17.4987L6.25 13.7487L7.45833 12.5404L10 15.082L12.5417 12.5404L13.75 13.7487L10 17.4987Z\"\r\n fill=\"#8486B9\"\r\n />\r\n <!-- Up arrow -->\r\n <path\r\n d=\"M7.45833 7.54036L6.25 6.33203L10 2.58203L13.75 6.33203L12.5417 7.54036L10 4.9987L7.45833 7.54036Z\"\r\n fill=\"#8486B9\"\r\n />\r\n</svg>\r\n\r\n\r\n</div>\r\n\r\n </div>\r\n </div>\r\n <div class=\"ngx-dropdown\" *ngIf=\"!!column.headerActionTemplate\" #headerDropdown>\r\n <a class=\"ngx-btn ngx-btn-link\" (click)=\"showHeaderActionTemplateMenu(column)\">\r\n <span class=\"ngx-icon ngx-icon-more\"></span>\r\n </a>\r\n <div\r\n class=\"ngx-menu ngx-table__table-menu\"\r\n *ngIf=\"column.key === openedHeaderActionTemplate\"\r\n >\r\n <ng-container [ngTemplateOutlet]=\"column.headerActionTemplate\"> </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"ngx-table__column-resizer\" *ngIf=\"config.resizeColumn && !last\"></div>\r\n </th>\r\n </ng-container>\r\n <th\r\n *ngIf=\"\r\n config.additionalActions ||\r\n config.detailsTemplate ||\r\n config.collapseAllRows ||\r\n config.groupRows\r\n \"\r\n class=\"ngx-table__header-cell-additional-actions\"\r\n >\r\n <div class=\"ngx-dropdown\" #additionalActionMenu *ngIf=\"config.additionalActions\">\r\n <a class=\"ngx-btn ngx-btn-link\" (click)=\"showMenu()\">\r\n <span class=\"ngx-icon ngx-icon-menu\"></span>\r\n </a>\r\n <ul class=\"ngx-menu ngx-table__table-menu\" *ngIf=\"menuActive\">\r\n <ng-container\r\n *ngIf=\"additionalActionsTemplate\"\r\n [ngTemplateOutlet]=\"additionalActionsTemplate\"\r\n >\r\n </ng-container>\r\n </ul>\r\n </div>\r\n </th>\r\n</tr>\r\n<tr\r\n [style.display]=\"config.searchEnabled && !filtersTemplate ? 'table-row' : 'none'\"\r\n class=\"ngx-table__search-header\"\r\n>\r\n <th *ngIf=\"config.checkboxes || config.radio\"></th>\r\n <ng-container *ngFor=\"let column of columns; let colIndex = index\">\r\n <th\r\n [ngClass]=\"column.cssClass && column.cssClass.includeHeader ? column.cssClass.name : ''\"\r\n [class.pinned-left]=\"column.pinned\"\r\n [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\r\n >\r\n <table-header\r\n *ngIf=\"getColumnDefinition(column)\"\r\n (update)=\"onSearch($event)\"\r\n [column]=\"column\"\r\n >\r\n </table-header>\r\n </th>\r\n </ng-container>\r\n <th *ngIf=\"config.additionalActions || config.detailsTemplate\"></th>\r\n</tr>\r\n<ng-container *ngIf=\"filtersTemplate\">\r\n <tr>\r\n <ng-container [ngTemplateOutlet]=\"filtersTemplate\"> </ng-container>\r\n </tr>\r\n</ng-container>\r\n","import { Injectable } from '@angular/core';\r\n\r\n@Injectable()\r\nexport class FiltersService {\r\n static getPath(p: string[], o: any): any {\r\n // https://github.com/dherges/ng-packagr/issues/696\r\n /* eslint-disable-next-line */\r\n const result = p.reduce((xs, x) => (xs && typeof xs[x] !== 'undefined' ? xs[x] : null), o);\r\n return result;\r\n }\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\nimport { FiltersService } from '../services/filters.service';\r\nimport { Config } from '..';\r\nimport { Subject } from 'rxjs';\r\n\r\n@Pipe({\r\n name: 'search',\r\n})\r\nexport class SearchPipe implements PipeTransform {\r\n private filters: { [key: string]: string } = {};\r\n\r\n transform(\r\n array: any[],\r\n filter: Array<{ value: string; key: string }>,\r\n filteredCountSubject: Subject<number>,\r\n config?: Config\r\n ): any {\r\n filteredCountSubject.next(0);\r\n if (typeof array === 'undefined') {\r\n return;\r\n }\r\n if (typeof filter === 'undefined') {\r\n filteredCountSubject.next(array.length);\r\n return array;\r\n }\r\n filter.forEach((f) => {\r\n this.filters[f.key] = f.value.toString().toLocaleLowerCase();\r\n if (Object.keys(f).length === 0 || f.value === '') {\r\n // eslint-disable-next-line\r\n delete this.filters[f.key];\r\n }\r\n });\r\n if (config && config.groupRows) {\r\n return array.map((arr) => this.filterGroup(arr, filteredCountSubject));\r\n }\r\n return this.filterGroup(array, filteredCountSubject);\r\n }\r\n\r\n private filterGroup(array: any[], filteredCountSubject: Subject<number>): any[] {\r\n const arr = array.filter((obj) => {\r\n return Object.keys(this.filters).every((c) => {\r\n const split = c.split('.');\r\n const val = FiltersService.getPath(split, obj);\r\n const element =\r\n typeof val === 'object' ? JSON.stringify(val) : val.toString().toLocaleLowerCase();\r\n const strings = this.filters[c].split(',');\r\n return strings.some((s) => element.indexOf(s.trim()) > -1);\r\n });\r\n });\r\n filteredCountSubject.next(arr.length);\r\n return arr;\r\n }\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\nimport { FiltersService } from '../services/filters.service';\r\n\r\n@Pipe({\r\n name: 'render',\r\n})\r\nexport class RenderPipe implements PipeTransform {\r\n transform(row: any, key: string): string {\r\n const split = key.split('.');\r\n\r\n return FiltersService.getPath(split, row);\r\n }\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\nimport { Subject } from 'rxjs';\r\n\r\n@Pipe({\r\n name: 'global',\r\n})\r\nexport class GlobalSearchPipe implements PipeTransform {\r\n transform(array: any[], filter: string, filteredCountSubject: Subject<number>): any {\r\n filteredCountSubject.next(0);\r\n if (typeof array === 'undefined') {\r\n return;\r\n }\r\n if (typeof filter === 'undefined' || Object.keys(filter).length === 0 || filter === '') {\r\n filteredCountSubject.next(array.length);\r\n return array;\r\n }\r\n const arr = array.filter((row) => {\r\n const element = JSON.stringify(Object.values(row));\r\n const strings = filter.split(',');\r\n return strings.some(\r\n (s) => element.toLocaleLowerCase().indexOf(s.trim().toLocaleLowerCase()) > -1\r\n );\r\n });\r\n filteredCountSubject.next(arr.length);\r\n\r\n return arr;\r\n }\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\nimport { FiltersService } from '../services/filters.service';\r\nimport { Config } from '..';\r\n\r\n@Pipe({\r\n name: 'sort',\r\n})\r\nexport class SortPipe implements PipeTransform {\r\n private defaultArray: any[] = [];\r\n\r\n private static isNaN(aV: any, bV: any): boolean {\r\n return isNaN(parseFloat(aV)) || !isFinite(aV) || isNaN(parseFloat(bV)) || !isFinite(bV);\r\n }\r\n\r\n private static compare(a: any[], b: any[], key: string): number {\r\n const split = key.split('.');\r\n const aPath = FiltersService.getPath(split, a);\r\n const bPath = FiltersService.getPath(split, b);\r\n const aValue = (aPath + '').toLowerCase();\r\n const bValue = (bPath + '').toLowerCase();\r\n if (SortPipe.isNaN(aPath, bPath)) {\r\n return aValue.localeCompare(bValue);\r\n }\r\n if (parseFloat(aPath) < parseFloat(bPath)) {\r\n return -1;\r\n }\r\n if (parseFloat(aPath) > parseFloat(bPath)) {\r\n return 1;\r\n }\r\n\r\n return 0;\r\n }\r\n\r\n transform(array: any[], filter: { order: string; key: string }, config?: Config): any[] {\r\n if (this.defaultArray.length === 0) {\r\n this.defaultArray = array;\r\n }\r\n if (!filter.key || filter.key === '') {\r\n return array;\r\n }\r\n if (filter.order === '') {\r\n return this.defaultArray;\r\n }\r\n if (filter.order === 'asc') {\r\n return this.sortAsc(array, filter, config);\r\n }\r\n return this.sortDesc(array, filter, config);\r\n }\r\n\r\n private sortAsc(array: any[], filter: { order: string; key: string }, config?: Config): any[] {\r\n if (config && config.groupRows) {\r\n return array.map((arr) => arr.sort((a, b) => SortPipe.compare(a, b, filter.key)));\r\n }\r\n return array.sort((a, b) => SortPipe.compare(a, b, filter.key));\r\n }\r\n\r\n private sortDesc(array: any[], filter: { order: string; key: string }, config?: Config): any[] {\r\n if (config && config.groupRows) {\r\n return array.map((arr) => arr.sort((a, b) => SortPipe.compare(b, a, filter.key)));\r\n }\r\n return array.sort((a, b) => SortPipe.compare(b, a, filter.key));\r\n }\r\n}\r\n","import { CdkDragDrop, CdkDragStart, moveItemInArray } from '@angular/cdk/drag-drop';\r\nimport {\r\n AfterViewInit,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChild,\r\n EventEmitter,\r\n HostListener,\r\n Input,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n Output,\r\n SimpleChange,\r\n SimpleChanges,\r\n TemplateRef,\r\n ViewChild,\r\n} from '@angular/core';\r\n\r\nimport { API, ApiType, Columns, Config, Event, Pagination } from '../..';\r\nimport { DefaultConfigService } from '../../services/config-service';\r\nimport { PaginationComponent, PaginationRange } from '../pagination/pagination.component';\r\nimport { GroupRowsService } from '../../services/group-rows.service';\r\nimport { StyleService } from '../../services/style.service';\r\nimport { Subject } from 'rxjs';\r\nimport { CdkVirtualScrollViewport, ScrollDispatcher } from '@angular/cdk/scrolling';\r\nimport { filter, takeUntil, throttleTime } from 'rxjs/operators';\r\n\r\ntype ColumnKeyType = string | number | boolean;\r\n\r\ninterface RowContextMenuPosition {\r\n top: string | null;\r\n left: string | null;\r\n value: any | null;\r\n}\r\n\r\n@Component({\r\n selector: 'ngx-table',\r\n providers: [DefaultConfigService, GroupRowsService, StyleService],\r\n templateUrl: './base.component.html',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class BaseComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {\r\n private unsubscribe = new Subject<void>();\r\n public selectedRow: number;\r\n public selectedCol: number;\r\n public term: any;\r\n public filterCount = -1;\r\n public filteredCountSubject = new Subject<number>();\r\n public tableClass: string | null = null;\r\n public globalSearchTerm: string;\r\n public grouped: any = [];\r\n public isSelected = false;\r\n public page = 1;\r\n public count = 0;\r\n public sortState = new Map();\r\n public sortKey: string | null = null;\r\n public rowContextMenuPosition: RowContextMenuPosition = {\r\n top: null,\r\n left: null,\r\n value: null,\r\n };\r\n public limit;\r\n public sortBy: { key: string } & { order: string } = {\r\n key: '',\r\n order: 'asc',\r\n };\r\n public selectedDetailsTemplateRowId = new Set<number>();\r\n public selectedCheckboxes = new Set<number>();\r\n public config: Config;\r\n\r\n @Input() configuration: Config;\r\n @Input() data: any[];\r\n @Input() pagination: Pagination;\r\n @Input() groupRowsBy: string;\r\n @Input() id = 'table';\r\n @Input() toggleRowIndex;\r\n @Input() detailsTemplate: TemplateRef<any>;\r\n @Input() summaryTemplate: TemplateRef<{ total: number; limit: number; page: number }>;\r\n @Input() groupRowsHeaderTemplate: TemplateRef<any>;\r\n @Input() filtersTemplate: TemplateRef<any>;\r\n @Input() selectAllTemplate: TemplateRef<any>;\r\n @Input() noResultsTemplate: TemplateRef<void>;\r\n @Input() loadingTemplate: TemplateRef<void>;\r\n @Input() additionalActionsTemplate: TemplateRef<void>;\r\n @Input() rowContextMenu: TemplateRef<any>;\r\n @Input() columns: Columns[];\r\n @Output() readonly event = new EventEmitter<{ event: string; value: any }>();\r\n @ContentChild(TemplateRef) public rowTemplate: TemplateRef<any>;\r\n @ViewChild('paginationComponent') private paginationComponent: PaginationComponent;\r\n @ViewChild('contextMenu') contextMenu;\r\n @ViewChild('table') table;\r\n @ViewChild(CdkVirtualScrollViewport) viewPort: CdkVirtualScrollViewport;\r\n\r\n @HostListener('document:click', ['$event.target'])\r\n public onContextMenuClick(targetElement: any): void {\r\n if (this.contextMenu && !this.contextMenu.nativeElement.contains(targetElement)) {\r\n this.rowContextMenuPosition = {\r\n top: null,\r\n left: null,\r\n value: null,\r\n };\r\n }\r\n }\r\n\r\n constructor(\r\n private readonly cdr: ChangeDetectorRef,\r\n private readonly scrollDispatcher: ScrollDispatcher,\r\n public readonly styleService: StyleService\r\n ) {\r\n this.filteredCountSubject.pipe(takeUntil(this.unsubscribe)).subscribe((count) => {\r\n setTimeout(() => {\r\n this.filterCount = count;\r\n this.cdr.detectChanges();\r\n });\r\n });\r\n }\r\n\r\n ngOnInit(): void {\r\n if (!this.columns) {\r\n console.error('[columns] property required!');\r\n }\r\n if (this.configuration) {\r\n this.config = this.configuration;\r\n } else {\r\n this.config = DefaultConfigService.config;\r\n }\r\n this.limit = this.config.rows;\r\n if (this.groupRowsBy) {\r\n this.grouped = GroupRowsService.doGroupRows(this.data, this.groupRowsBy);\r\n }\r\n this.doDecodePersistedState();\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.unsubscribe.next();\r\n this.unsubscribe.complete();\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n const throttleValue = this.config.infiniteScrollThrottleTime\r\n ? this.config.infiniteScrollThrottleTime\r\n : 200;\r\n this.scrollDispatcher\r\n .scrolled()\r\n .pipe(\r\n throttleTime(throttleValue),\r\n filter((event) => {\r\n return (\r\n !!event &&\r\n this.viewPort &&\r\n this.viewPort.getRenderedRange().end === this.viewPort.getDataLength()\r\n );\r\n }),\r\n takeUntil(this.unsubscribe)\r\n )\r\n .subscribe(() => {\r\n this.emitEvent(Event.onInfiniteScrollEnd, null);\r\n });\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n const { configuration, data, pagination, groupRowsBy } = changes;\r\n this.toggleRowIndex = changes.toggleRowIndex;\r\n if (configuration && configuration.currentValue) {\r\n this.config = configuration.currentValue;\r\n }\r\n if (data && data.currentValue) {\r\n this.doApplyData(data);\r\n }\r\n if (pagination && pagination.currentValue) {\r\n const { count, limit, offset } = pagination.currentValue as Pagination;\r\n this.count = count;\r\n this.limit = limit;\r\n this.page = offset;\r\n }\r\n if (groupRowsBy && groupRowsBy.currentValue) {\r\n this.grouped = GroupRowsService.doGroupRows(this.data, this.groupRowsBy);\r\n }\r\n if (this.toggleRowIndex && this.toggleRowIndex.currentValue) {\r\n const row = this.toggleRowIndex.currentValue;\r\n this.collapseRow(row.index);\r\n }\r\n }\r\n\r\n orderBy(column: Columns): void {\r\n if (typeof column.orderEnabled !== 'undefined' && !column.orderEnabled) {\r\n return;\r\n }\r\n this.sortKey = column.key;\r\n if (!this.config.orderEnabled || this.sortKey === '') {\r\n return;\r\n }\r\n\r\n this.setColumnOrder(column);\r\n if (!this.config.orderEventOnly && !column.orderEventOnly) {\r\n this.sortBy.key = this.sortKey;\r\n this.sortBy.order = this.sortState.get(this.sortKey);\r\n } else {\r\n this.sortBy.key = '';\r\n this.sortBy.order = '';\r\n }\r\n if (!this.config.serverPagination) {\r\n this.data = [...this.data];\r\n this.sortBy = { ...this.sortBy };\r\n }\r\n\r\n const value = {\r\n key: this.sortKey,\r\n order: this.sortState.get(this.sortKey),\r\n };\r\n this.emitEvent(Event.onOrder, value);\r\n }\r\n\r\n onClick($event: MouseEvent, row: any, key: ColumnKeyType, colIndex: any, rowIndex: number): void {\r\n if (this.config.selectRow) {\r\n this.selectedRow = rowIndex;\r\n }\r\n if (this.config.selectCol && `${colIndex}`) {\r\n this.selectedCol = colIndex;\r\n }\r\n if (this.config.selectCell && `${colIndex}`) {\r\n this.selectedRow = rowIndex;\r\n this.selectedCol = colIndex;\r\n }\r\n\r\n if (this.config.clickEvent) {\r\n const value = {\r\n event: $event,\r\n row,\r\n key,\r\n rowId: rowIndex,\r\n colId: colIndex,\r\n };\r\n this.emitEvent(Event.onClick, value);\r\n }\r\n }\r\n\r\n onDoubleClick(\r\n $event: MouseEvent,\r\n row: any,\r\n key: ColumnKeyType,\r\n colIndex: any,\r\n rowIndex: number\r\n ): void {\r\n const value = {\r\n event: $event,\r\n row,\r\n key,\r\n rowId: rowIndex,\r\n colId: colIndex,\r\n };\r\n this.emitEvent(Event.onDoubleClick, value);\r\n }\r\n\r\n onCheckboxSelect($event: any, row: any, rowIndex: number): void {\r\n const value = {\r\n event: $event,\r\n row,\r\n rowId: rowIndex,\r\n };\r\n this.emitEvent(Event.onCheckboxSelect, value);\r\n }\r\n\r\n onRadioSelect($event: any, row: any, rowIndex: number): void {\r\n const value = {\r\n event: $event,\r\n row,\r\n rowId: rowIndex,\r\n };\r\n this.emitEvent(Event.onRadioSelect, value);\r\n }\r\n\r\n onSelectAll(): void {\r\n this.isSelected = !this.isSelected;\r\n this.emitEvent(Event.onSelectAll, this.isSelected);\r\n }\r\n\r\n onSearch($event: Array<{ key: string; value: string }>): void {\r\n if (!this.config.serverPagination) {\r\n this.term = $event;\r\n }\r\n this.emitEvent(Event.onSearch, $event);\r\n }\r\n\r\n onGlobalSearch(value: string): void {\r\n if (!this.config.serverPagination) {\r\n this.globalSearchTerm = value;\r\n }\r\n this.emitEvent(Event.onGlobalSearch, value);\r\n }\r\n\r\n onPagination(pagination: PaginationRange): void {\r\n this.page = pagination.page;\r\n this.limit = pagination.limit;\r\n this.config.rows = pagination.limit;\r\n this.emitEvent(Event.onPagination, pagination);\r\n }\r\n\r\n toggleCheckbox(rowIndex: number): void {\r\n this.selectedCheckboxes.has(rowIndex)\r\n ? this.selectedCheckboxes.delete(rowIndex)\r\n : this.selectedCheckboxes.add(rowIndex);\r\n }\r\n\