UNPKG

ngx-easy-table

Version:
1,999 lines 88.4 kB
import { CommonModule } from '@angular/common';
import { Injectable, EventEmitter, Component, ChangeDetectionStrategy, ViewChild, Input, Output, HostListener, ChangeDetectorRef, ContentChild, TemplateRef, Pipe, NgModule } from '@angular/core';
import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
import { NgxPaginationModule } from 'ngx-pagination';
import { from, Subject } from 'rxjs';
import { groupBy, flatMap, reduce, takeUntil, throttleTime, filter } from 'rxjs/operators';
import { ScrollDispatcher, CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function Columns() { }
if (false) {
    /** @type {?} */
    Columns.prototype.key;
    /** @type {?} */
    Columns.prototype.title;
    /** @type {?|undefined} */
    Columns.prototype.placeholder;
    /** @type {?|undefined} */
    Columns.prototype.width;
    /** @type {?|undefined} */
    Columns.prototype.cellTemplate;
    /** @type {?|undefined} */
    Columns.prototype.orderEnabled;
    /** @type {?|undefined} */
    Columns.prototype.orderEventOnly;
    /** @type {?|undefined} */
    Columns.prototype.searchEnabled;
    /** @type {?|undefined} */
    Columns.prototype.orderBy;
    /** @type {?|undefined} */
    Columns.prototype.cssClass;
    /** @type {?|undefined} */
    Columns.prototype.pinned;
    /** @type {?|undefined} */
    Columns.prototype.headerActionTemplate;
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function Config() { }
if (false) {
    /** @type {?} */
    Config.prototype.searchEnabled;
    /** @type {?} */
    Config.prototype.headerEnabled;
    /** @type {?} */
    Config.prototype.orderEnabled;
    /** @type {?|undefined} */
    Config.prototype.orderEventOnly;
    /** @type {?} */
    Config.prototype.paginationEnabled;
    /** @type {?|undefined} */
    Config.prototype.exportEnabled;
    /** @type {?} */
    Config.prototype.clickEvent;
    /** @type {?} */
    Config.prototype.selectRow;
    /** @type {?} */
    Config.prototype.selectCol;
    /** @type {?} */
    Config.prototype.selectCell;
    /** @type {?} */
    Config.prototype.rows;
    /** @type {?} */
    Config.prototype.additionalActions;
    /** @type {?} */
    Config.prototype.serverPagination;
    /** @type {?} */
    Config.prototype.isLoading;
    /** @type {?} */
    Config.prototype.detailsTemplate;
    /** @type {?} */
    Config.prototype.groupRows;
    /** @type {?} */
    Config.prototype.paginationRangeEnabled;
    /** @type {?} */
    Config.prototype.collapseAllRows;
    /** @type {?} */
    Config.prototype.checkboxes;
    /** @type {?|undefined} */
    Config.prototype.radio;
    /** @type {?} */
    Config.prototype.resizeColumn;
    /** @type {?} */
    Config.prototype.fixedColumnWidth;
    /** @type {?} */
    Config.prototype.horizontalScroll;
    /** @type {?} */
    Config.prototype.draggable;
    /** @type {?} */
    Config.prototype.logger;
    /** @type {?|undefined} */
    Config.prototype.showDetailsArrow;
    /** @type {?|undefined} */
    Config.prototype.showContextMenu;
    /** @type {?|undefined} */
    Config.prototype.persistState;
    /** @type {?|undefined} */
    Config.prototype.paginationMaxSize;
    /** @type {?|undefined} */
    Config.prototype.threeWaySort;
    /** @type {?|undefined} */
    Config.prototype.columnReorder;
    /** @type {?|undefined} */
    Config.prototype.rowReorder;
    /** @type {?|undefined} */
    Config.prototype.infiniteScroll;
    /** @type {?|undefined} */
    Config.prototype.infiniteScrollThrottleTime;
    /** @type {?} */
    Config.prototype.tableLayout;
}
/** @enum {string} */
const STYLE = {
    TINY: 'tiny',
    BIG: 'big',
    NORMAL: 'normal',
};
/** @enum {string} */
const THEME = {
    LIGHT: 'light',
    DARK: 'dark',
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/** @enum {string} */
const Event = {
    onPagination: 'onPagination',
    onOrder: 'onOrder',
    onGlobalSearch: 'onGlobalSearch',
    onSearch: 'onSearch',
    onClick: 'onClick',
    onDoubleClick: 'onDoubleClick',
    onCheckboxSelect: 'onCheckboxSelect',
    onRadioSelect: 'onRadioSelect',
    onCheckboxToggle: 'onCheckboxToggle',
    onSelectAll: 'onSelectAll',
    onInfiniteScrollEnd: 'onInfiniteScrollEnd',
    onColumnResizeMouseDown: 'onColumnResizeMouseDown',
    onColumnResizeMouseUp: 'onColumnResizeMouseUp',
    onRowDrop: 'onRowDrop',
    onRowCollapsedShow: 'onRowCollapsedShow',
    onRowCollapsedHide: 'onRowCollapsedHide',
    onRowContextMenu: 'onRowContextMenu',
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function Pagination() { }
if (false) {
    /** @type {?} */
    Pagination.prototype.limit;
    /** @type {?} */
    Pagination.prototype.offset;
    /** @type {?} */
    Pagination.prototype.count;
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/** @enum {string} */
const API = {
    rowContextMenuClicked: 'rowContextMenuClicked',
    setInputValue: 'setInputValue',
    toolPanelClicked: 'toolPanelClicked',
    toggleRowIndex: 'toggleRowIndex',
    toggleCheckbox: 'toggleCheckbox',
    onGlobalSearch: 'onGlobalSearch',
    setPaginationCurrentPage: 'setPaginationCurrentPage',
    getPaginationCurrentPage: 'getPaginationCurrentPage',
    getPaginationTotalItems: 'getPaginationTotalItems',
    getNumberOfRowsPerPage: 'getNumberOfRowsPerPage',
    getPaginationLastPage: 'getPaginationLastPage',
    setPaginationRange: 'setPaginationRange',
    setPaginationPreviousLabel: 'setPaginationPreviousLabel',
    setPaginationNextLabel: 'setPaginationNextLabel',
    setPaginationDisplayLimit: 'setPaginationDisplayLimit',
    setTableClass: 'setTableClass',
    setRowClass: 'setRowClass',
    setCellClass: 'setCellClass',
    setRowStyle: 'setRowStyle',
    setCellStyle: 'setCellStyle',
    sortBy: 'sortBy',
};
/**
 * @record
 */
function RowClass() { }
if (false) {
    /** @type {?} */
    RowClass.prototype.row;
    /** @type {?} */
    RowClass.prototype.className;
}
/**
 * @record
 */
function CellClass() { }
if (false) {
    /** @type {?} */
    CellClass.prototype.row;
    /** @type {?} */
    CellClass.prototype.cell;
    /** @type {?} */
    CellClass.prototype.className;
}
/**
 * @record
 */
function RowStyle() { }
if (false) {
    /** @type {?} */
    RowStyle.prototype.row;
    /** @type {?} */
    RowStyle.prototype.attr;
    /** @type {?} */
    RowStyle.prototype.value;
}
/**
 * @record
 */
function CellStyle() { }
if (false) {
    /** @type {?} */
    CellStyle.prototype.row;
    /** @type {?} */
    CellStyle.prototype.cell;
    /** @type {?} */
    CellStyle.prototype.attr;
    /** @type {?} */
    CellStyle.prototype.value;
}
/**
 * @record
 */
function APIDefinition() { }
if (false) {
    /**
     * @template B
     * @param {?} event
     * @return {?}
     */
    APIDefinition.prototype.apiEvent = function (event) { };
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/** @type {?} */
const DefaultConfig = {
    searchEnabled: false,
    headerEnabled: true,
    orderEnabled: true,
    orderEventOnly: false,
    paginationEnabled: true,
    exportEnabled: false,
    clickEvent: true,
    selectRow: false,
    selectCol: false,
    selectCell: false,
    rows: 10,
    additionalActions: false,
    serverPagination: false,
    isLoading: false,
    detailsTemplate: false,
    groupRows: false,
    paginationRangeEnabled: true,
    collapseAllRows: false,
    checkboxes: false,
    radio: false,
    resizeColumn: false,
    fixedColumnWidth: true,
    horizontalScroll: false,
    draggable: false,
    logger: false,
    showDetailsArrow: false,
    showContextMenu: false,
    persistState: false,
    paginationMaxSize: 5,
    threeWaySort: false,
    tableLayout: {
        style: STYLE.NORMAL,
        theme: THEME.LIGHT,
        borderless: false,
        hover: true,
        striped: false,
    },
};
class DefaultConfigService {
}
DefaultConfigService.config = DefaultConfig;
DefaultConfigService.decorators = [
    { type: Injectable }
];
if (false) {
    /** @type {?} */
    DefaultConfigService.config;
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function PaginationRange() { }
if (false) {
    /** @type {?} */
    PaginationRange.prototype.page;
    /** @type {?} */
    PaginationRange.prototype.limit;
}
class PaginationComponent {
    constructor() {
        this.updateRange = new EventEmitter();
        this.ranges = [5, 10, 25, 50, 100];
        this.showRange = false;
        this.screenReaderPaginationLabel = 'Pagination';
        this.screenReaderPageLabel = 'page';
        this.screenReaderCurrentLabel = 'You are on page';
        this.previousLabel = '';
        this.nextLabel = '';
        this.directionLinks = true;
    }
    /**
     * @param {?} targetElement
     * @return {?}
     */
    onClick(targetElement) {
        if (this.paginationRange && !this.paginationRange.nativeElement.contains(targetElement)) {
            this.showRange = false;
        }
    }
    /**
     * @param {?} changes
     * @return {?}
     */
    ngOnChanges(changes) {
        const { config } = changes;
        if (config && config.currentValue) {
            this.selectedLimit = this.config.rows;
        }
    }
    /**
     * @param {?} page
     * @return {?}
     */
    onPageChange(page) {
        this.updateRange.emit({
            page,
            limit: this.selectedLimit,
        });
    }
    /**
     * @param {?} limit
     * @param {?} callFromAPI
     * @return {?}
     */
    changeLimit(limit, callFromAPI) {
        if (!callFromAPI) {
            this.showRange = !this.showRange;
        }
        this.selectedLimit = limit;
        this.updateRange.emit({
            page: 1,
            limit,
        });
    }
}
PaginationComponent.decorators = [
    { type: Component, args: [{
                selector: 'pagination',
                template: "<div class=\"ngx-pagination-wrapper\"\n     [style.display]=\"config.paginationEnabled ? '' : 'none'\"\n     [class.ngx-table__table--dark-pagination-wrapper]=\"config.tableLayout.theme === 'dark'\">\n  <div class=\"ngx-pagination-steps\">\n    <pagination-template\n      #paginationDirective=\"paginationApi\"\n      id=\"pagination-controls\"\n      [id]=\"id\"\n      [class.ngx-table__table--dark-pagination]=\"config.tableLayout.theme === 'dark'\"\n      [maxSize]=\"config.paginationMaxSize || 5\"\n      (pageChange)=\"onPageChange($event)\">\n      <ul class=\"ngx-pagination\"\n          role=\"navigation\"\n          [attr.aria-label]=\"screenReaderPaginationLabel\"\n          [class.responsive]=\"true\">\n        <li class=\"pagination-previous\" [class.disabled]=\"paginationDirective.isFirstPage()\" *ngIf=\"directionLinks\">\n          <a tabindex=\"0\" *ngIf=\"1 < paginationDirective.getCurrent()\" (keyup.enter)=\"paginationDirective.previous()\"\n             (click)=\"paginationDirective.previous()\"\n             [attr.aria-label]=\"previousLabel + ' ' + screenReaderPageLabel\">\n            {{ previousLabel }} <span class=\"show-for-sr\">{{ screenReaderPageLabel }}</span>\n          </a>\n          <span *ngIf=\"paginationDirective.isFirstPage()\">\n                {{ previousLabel }} <span class=\"show-for-sr\">{{ screenReaderPageLabel }}</span>\n            </span>\n        </li>\n        <li class=\"small-screen\">\n          {{ paginationDirective.getCurrent() }} / {{ paginationDirective.getLastPage() }}\n        </li>\n        <li [class.current]=\"paginationDirective.getCurrent() === page.value\"\n            [class.ellipsis]=\"page.label === '...'\"\n            *ngFor=\"let page of paginationDirective.pages\">\n          <a tabindex=\"0\" (keyup.enter)=\"paginationDirective.setCurrent(page.value)\"\n             (click)=\"paginationDirective.setCurrent(page.value)\"\n             *ngIf=\"paginationDirective.getCurrent() !== page.value\">\n            <span class=\"show-for-sr\">{{ screenReaderPageLabel }} </span>\n            <span>{{ page.label }}</span>\n          </a>\n          <ng-container *ngIf=\"paginationDirective.getCurrent() === page.value\">\n            <span class=\"show-for-sr\">{{ screenReaderCurrentLabel }} </span>\n            <span>{{ page.label }}</span>\n          </ng-container>\n        </li>\n        <li class=\"pagination-next\" [class.disabled]=\"paginationDirective.isLastPage()\" *ngIf=\"directionLinks\">\n          <a tabindex=\"0\" *ngIf=\"!paginationDirective.isLastPage()\" (keyup.enter)=\"paginationDirective.next()\"\n             (click)=\"paginationDirective.next()\"\n             [attr.aria-label]=\"nextLabel + ' ' + screenReaderPageLabel\">\n            {{ nextLabel }} <span class=\"show-for-sr\">{{ screenReaderPageLabel }}</span>\n          </a>\n          <span *ngIf=\"paginationDirective.isLastPage()\">\n                 {{ nextLabel }} <span class=\"show-for-sr\">{{ screenReaderPageLabel }}</span>\n            </span>\n        </li>\n      </ul>\n    </pagination-template>\n  </div>\n  <div class=\"ngx-pagination-range\"\n       #paginationRange\n       [class.ngx-table__table--dark-pagination-range]=\"config.tableLayout.theme === 'dark'\"\n       *ngIf=\"config.paginationRangeEnabled\">\n    <div class=\"ngx-dropdown ngx-pagination-range-dropdown\"\n         id=\"rowAmount\">\n      <div class=\"ngx-btn-group\">\n        <div class=\"ngx-pagination-range-dropdown-button\"\n             (click)=\"showRange = !showRange\">\n          {{selectedLimit}} <i class=\"ngx-icon ngx-icon-arrow-down\"></i>\n        </div>\n        <ul class=\"ngx-menu\" *ngIf=\"showRange\">\n          <li class=\"ngx-pagination-range-dropdown-button-item\"\n              [class.ngx-pagination-range--selected]=\"limit === selectedLimit\"\n              (click)=\"changeLimit(limit, false)\"\n              *ngFor=\"let limit of ranges\">\n            <span>{{limit}}</span>\n          </li>\n        </ul>\n      </div>\n    </div>\n  </div>\n</div>\n",
                changeDetection: ChangeDetectionStrategy.OnPush
            }] }
];
PaginationComponent.propDecorators = {
    paginationDirective: [{ type: ViewChild, args: ['paginationDirective', { static: true },] }],
    paginationRange: [{ type: ViewChild, args: ['paginationRange', { static: false },] }],
    pagination: [{ type: Input }],
    config: [{ type: Input }],
    id: [{ type: Input }],
    updateRange: [{ type: Output }],
    onClick: [{ type: HostListener, args: ['document:click', ['$event.target'],] }]
};
if (false) {
    /** @type {?} */
    PaginationComponent.prototype.paginationDirective;
    /** @type {?} */
    PaginationComponent.prototype.paginationRange;
    /** @type {?} */
    PaginationComponent.prototype.pagination;
    /** @type {?} */
    PaginationComponent.prototype.config;
    /** @type {?} */
    PaginationComponent.prototype.id;
    /** @type {?} */
    PaginationComponent.prototype.updateRange;
    /** @type {?} */
    PaginationComponent.prototype.ranges;
    /** @type {?} */
    PaginationComponent.prototype.selectedLimit;
    /** @type {?} */
    PaginationComponent.prototype.showRange;
    /** @type {?} */
    PaginationComponent.prototype.screenReaderPaginationLabel;
    /** @type {?} */
    PaginationComponent.prototype.screenReaderPageLabel;
    /** @type {?} */
    PaginationComponent.prototype.screenReaderCurrentLabel;
    /** @type {?} */
    PaginationComponent.prototype.previousLabel;
    /** @type {?} */
    PaginationComponent.prototype.nextLabel;
    /** @type {?} */
    PaginationComponent.prototype.directionLinks;
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class GroupRowsService {
    /**
     * @template T
     * @param {?} data
     * @param {?} groupRowsBy
     * @return {?}
     */
    static doGroupRows(data, groupRowsBy) {
        /** @type {?} */
        const grouped = [];
        from(data).pipe(groupBy((/**
         * @param {?} row
         * @return {?}
         */
        (row) => row[groupRowsBy])), flatMap((/**
         * @param {?} group
         * @return {?}
         */
        (group) => group.pipe(reduce((/**
         * @param {?} acc
         * @param {?} curr
         * @return {?}
         */
        (acc, curr) => [...acc, curr]), []))))).subscribe((/**
         * @param {?} row
         * @return {?}
         */
        (row) => grouped.push(row)));
        return grouped;
    }
}
GroupRowsService.decorators = [
    { type: Injectable }
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/* tslint:disable:no-useless-cast */
class StyleService {
    /**
     * @param {?} val
     * @return {?}
     */
    setRowClass(val) {
        /** @type {?} */
        const selector = `#table > tbody > tr:nth-child(${val.row})`;
        /** @type {?} */
        const row = (/** @type {?} */ (document.querySelector(selector)));
        if (row) {
            row.classList.add(val.className);
        }
    }
    /**
     * @param {?} val
     * @return {?}
     */
    setCellClass(val) {
        /** @type {?} */
        const selector = `#table > tbody > tr:nth-child(${val.row}) > td:nth-child(${val.cell})`;
        /** @type {?} */
        const cell = (/** @type {?} */ (document.querySelector(selector)));
        if (cell) {
            cell.classList.add(val.className);
        }
    }
    /**
     * @param {?} val
     * @return {?}
     */
    setRowStyle(val) {
        /** @type {?} */
        const selector = `#table > tbody > tr:nth-child(${val.row})`;
        /** @type {?} */
        const row = (/** @type {?} */ (document.querySelector(selector)));
        if (row) {
            // tslint:disable-next-line:no-string-literal
            row.style[val.attr] = val.value;
        }
    }
    /**
     * @param {?} val
     * @return {?}
     */
    setCellStyle(val) {
        /** @type {?} */
        const selector = `#table > tbody > tr:nth-child(${val.row}) > td:nth-child(${val.cell})`;
        /** @type {?} */
        const cell = (/** @type {?} */ (document.querySelector(selector)));
        if (cell) {
            // tslint:disable-next-line:no-string-literal
            cell.style[val.attr] = val.value;
        }
    }
    /**
     * @param {?} pinned
     * @param {?} column
     * @return {?}
     */
    pinnedWidth(pinned, column) {
        if (pinned) {
            return 150 * column + 'px';
        }
    }
}
StyleService.decorators = [
    { type: Injectable }
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function RowContextMenuPosition() { }
if (false) {
    /** @type {?} */
    RowContextMenuPosition.prototype.top;
    /** @type {?} */
    RowContextMenuPosition.prototype.left;
    /** @type {?} */
    RowContextMenuPosition.prototype.value;
}
class BaseComponent {
    /**
     * @param {?} cdr
     * @param {?} scrollDispatcher
     * @param {?} styleService
     */
    constructor(cdr, scrollDispatcher, styleService) {
        this.cdr = cdr;
        this.scrollDispatcher = scrollDispatcher;
        this.styleService = styleService;
        this.unsubscribe = new Subject();
        this.filterCount = -1;
        this.filteredCountSubject = new Subject();
        this.tableClass = null;
        this.grouped = [];
        this.isSelected = false;
        this.page = 1;
        this.count = 0;
        this.sortState = new Map();
        this.sortKey = null;
        this.rowContextMenuPosition = {
            top: null,
            left: null,
            value: null,
        };
        this.sortBy = {
            key: '',
            order: 'asc',
        };
        this.selectedDetailsTemplateRowId = new Set();
        this.selectedCheckboxes = new Set();
        this.loadingHeight = '30px';
        this.id = 'table';
        this.event = new EventEmitter();
        this.subscription = this.filteredCountSubject
            .pipe(takeUntil(this.unsubscribe))
            .subscribe((/**
         * @param {?} count
         * @return {?}
         */
        (count) => {
            this.filterCount = count;
            this.cdr.detectChanges();
        }));
    }
    /**
     * @param {?} targetElement
     * @return {?}
     */
    onContextMenuClick(targetElement) {
        if (this.contextMenu && !this.contextMenu.nativeElement.contains(targetElement)) {
            this.rowContextMenuPosition = {
                top: null,
                left: null,
                value: null,
            };
        }
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        if (!this.columns) {
            console.error('[columns] property required!');
        }
        if (this.configuration) {
            this.config = this.configuration;
        }
        else {
            this.config = DefaultConfigService.config;
        }
        this.limit = this.config.rows;
        if (this.groupRowsBy) {
            this.grouped = GroupRowsService.doGroupRows(this.data, this.groupRowsBy);
        }
        this.doDecodePersistedState();
    }
    /**
     * @return {?}
     */
    ngOnDestroy() {
        this.unsubscribe.next();
        this.unsubscribe.complete();
    }
    /**
     * @return {?}
     */
    ngAfterViewInit() {
        /** @type {?} */
        const throttleValue = this.config.infiniteScrollThrottleTime ?
            this.config.infiniteScrollThrottleTime :
            200;
        this.scrollDispatcher.scrolled()
            .pipe(takeUntil(this.unsubscribe), throttleTime(throttleValue), filter((/**
         * @param {?} event
         * @return {?}
         */
        (event) => {
            return !!event && this.viewPort && this.viewPort.getRenderedRange().end === this.viewPort.getDataLength();
        })))
            .subscribe((/**
         * @return {?}
         */
        () => {
            this.emitEvent(Event.onInfiniteScrollEnd, null);
        }));
    }
    /**
     * @param {?} changes
     * @return {?}
     */
    ngOnChanges(changes) {
        const { configuration, data, pagination, groupRowsBy } = changes;
        this.toggleRowIndex = changes.toggleRowIndex;
        if (configuration && configuration.currentValue) {
            this.config = configuration.currentValue;
        }
        if (data && data.currentValue) {
            this.doApplyData(data);
        }
        if (pagination && pagination.currentValue) {
            const { count, limit, offset } = (/** @type {?} */ (pagination.currentValue));
            this.count = count;
            this.limit = limit;
            this.page = offset;
        }
        if (groupRowsBy && groupRowsBy.currentValue) {
            this.grouped = GroupRowsService.doGroupRows(this.data, this.groupRowsBy);
        }
        if (this.toggleRowIndex && this.toggleRowIndex.currentValue) {
            /** @type {?} */
            const row = this.toggleRowIndex.currentValue;
            this.collapseRow(row.index);
        }
    }
    /**
     * @param {?} column
     * @return {?}
     */
    orderBy(column) {
        if (typeof column.orderEnabled !== 'undefined' && !column.orderEnabled) {
            return;
        }
        this.sortKey = column.key;
        if (!this.config.orderEnabled || this.sortKey === '') {
            return;
        }
        this.setColumnOrder(this.sortKey);
        if (!this.config.orderEventOnly && !column.orderEventOnly) {
            this.sortBy.key = this.sortKey;
            this.sortBy.order = this.sortState.get(this.sortKey);
        }
        else {
            this.sortBy.key = '';
            this.sortBy.order = '';
        }
        if (!this.config.serverPagination) {
            this.data = [...this.data];
            this.sortBy = Object.assign({}, this.sortBy);
        }
        /** @type {?} */
        const value = {
            key: this.sortKey,
            order: this.sortState.get(this.sortKey),
        };
        this.emitEvent(Event.onOrder, value);
    }
    /**
     * @param {?} $event
     * @param {?} row
     * @param {?} key
     * @param {?} colIndex
     * @param {?} rowIndex
     * @return {?}
     */
    onClick($event, row, key, colIndex, rowIndex) {
        if (this.config.selectRow) {
            this.selectedRow = rowIndex;
        }
        if (this.config.selectCol && colIndex) {
            this.selectedCol = colIndex;
        }
        if (this.config.selectCell && colIndex) {
            this.selectedRow = rowIndex;
            this.selectedCol = colIndex;
        }
        if (this.config.clickEvent) {
            /** @type {?} */
            const value = {
                event: $event,
                row,
                key,
                rowId: rowIndex,
                colId: colIndex,
            };
            this.emitEvent(Event.onClick, value);
        }
    }
    /**
     * @param {?} $event
     * @param {?} row
     * @param {?} key
     * @param {?} colIndex
     * @param {?} rowIndex
     * @return {?}
     */
    onDoubleClick($event, row, key, colIndex, rowIndex) {
        /** @type {?} */
        const value = {
            event: $event,
            row,
            key,
            rowId: rowIndex,
            colId: colIndex,
        };
        this.emitEvent(Event.onDoubleClick, value);
    }
    /**
     * @param {?} $event
     * @param {?} row
     * @param {?} rowIndex
     * @return {?}
     */
    onCheckboxSelect($event, row, rowIndex) {
        /** @type {?} */
        const value = {
            event: $event,
            row,
            rowId: rowIndex,
        };
        this.emitEvent(Event.onCheckboxSelect, value);
    }
    /**
     * @param {?} $event
     * @param {?} row
     * @param {?} rowIndex
     * @return {?}
     */
    onRadioSelect($event, row, rowIndex) {
        /** @type {?} */
        const value = {
            event: $event,
            row,
            rowId: rowIndex,
        };
        this.emitEvent(Event.onRadioSelect, value);
    }
    /**
     * @return {?}
     */
    onSelectAll() {
        this.isSelected = !this.isSelected;
        this.emitEvent(Event.onSelectAll, this.isSelected);
    }
    /**
     * @param {?} $event
     * @return {?}
     */
    onSearch($event) {
        if (!this.config.serverPagination) {
            this.term = $event;
        }
        this.emitEvent(Event.onSearch, $event);
    }
    /**
     * @param {?} value
     * @return {?}
     */
    onGlobalSearch(value) {
        if (!this.config.serverPagination) {
            this.globalSearchTerm = value;
        }
        this.emitEvent(Event.onGlobalSearch, value);
    }
    /**
     * @param {?} pagination
     * @return {?}
     */
    onPagination(pagination) {
        this.page = pagination.page;
        this.limit = pagination.limit;
        this.emitEvent(Event.onPagination, pagination);
    }
    /**
     * @param {?} rowIndex
     * @return {?}
     */
    toggleCheckbox(rowIndex) {
        this.selectedCheckboxes.has(rowIndex) ?
            this.selectedCheckboxes.delete(rowIndex) :
            this.selectedCheckboxes.add(rowIndex);
    }
    /**
     * @param {?} rowIndex
     * @return {?}
     */
    collapseRow(rowIndex) {
        if (this.selectedDetailsTemplateRowId.has(rowIndex)) {
            this.selectedDetailsTemplateRowId.delete(rowIndex);
            this.emitEvent(Event.onRowCollapsedHide, rowIndex);
        }
        else {
            this.selectedDetailsTemplateRowId.add(rowIndex);
            this.emitEvent(Event.onRowCollapsedShow, rowIndex);
        }
    }
    /**
     * @private
     * @return {?}
     */
    doDecodePersistedState() {
        if (!this.config.persistState) {
            return;
        }
        /** @type {?} */
        const pagination = localStorage.getItem(Event.onPagination);
        /** @type {?} */
        const sort = localStorage.getItem(Event.onOrder);
        /** @type {?} */
        const search = localStorage.getItem(Event.onSearch);
        if (pagination) {
            this.onPagination(JSON.parse(pagination));
        }
        if (sort) {
            const { key, order } = JSON.parse(sort);
            this.bindApi({
                type: API.sortBy,
                value: { column: key, order },
            });
        }
        if (search) {
            this.bindApi({
                type: API.setInputValue,
                value: JSON.parse(search),
            });
        }
    }
    /**
     * @param {?} rowIndex
     * @return {?}
     */
    isRowCollapsed(rowIndex) {
        if (this.config.collapseAllRows) {
            return true;
        }
        return this.selectedDetailsTemplateRowId.has(rowIndex);
    }
    /**
     * @return {?}
     */
    get isLoading() {
        /** @type {?} */
        const table = (/** @type {?} */ (document.getElementById(this.id)));
        if (table && table.rows && table.rows.length > 3) {
            this.getLoadingHeight(table.rows);
        }
        return this.config.isLoading;
    }
    /**
     * @param {?} rows
     * @return {?}
     */
    getLoadingHeight(rows) {
        /** @type {?} */
        const searchEnabled = this.config.searchEnabled ? 1 : 0;
        /** @type {?} */
        const headerEnabled = this.config.headerEnabled ? 1 : 0;
        /** @type {?} */
        const borderTrHeight = 1;
        /** @type {?} */
        const borderDivHeight = 2;
        this.loadingHeight = (rows.length - searchEnabled - headerEnabled) * (rows[3].offsetHeight - borderTrHeight) - borderDivHeight + 'px';
    }
    /**
     * @return {?}
     */
    get arrowDefinition() {
        return this.config.showDetailsArrow || typeof this.config.showDetailsArrow === 'undefined';
    }
    /**
     * @param {?} $event
     * @param {?} row
     * @param {?} key
     * @param {?} colIndex
     * @param {?} rowIndex
     * @return {?}
     */
    onRowContextMenu($event, row, key, colIndex, rowIndex) {
        if (!this.config.showContextMenu) {
            return;
        }
        $event.preventDefault();
        /** @type {?} */
        const value = {
            event: $event,
            row,
            key,
            rowId: rowIndex,
            colId: colIndex,
        };
        this.rowContextMenuPosition = {
            top: `${$event.y - 10}px`,
            left: `${$event.x - 10}px`,
            value,
        };
        this.emitEvent(Event.onRowContextMenu, value);
    }
    /**
     * @private
     * @param {?} data
     * @return {?}
     */
    doApplyData(data) {
        /** @type {?} */
        const order = this.columns.find((/**
         * @param {?} c
         * @return {?}
         */
        (c) => !!c.orderBy));
        if (order) {
            this.sortState.set(this.sortKey, (order.orderBy === 'asc') ? 'desc' : 'asc');
            this.orderBy(order);
        }
        else {
            this.data = [...data.currentValue];
        }
    }
    /**
     * @param {?} event
     * @return {?}
     */
    onDrop(event) {
        this.emitEvent(Event.onRowDrop, event);
        moveItemInArray(this.data, event.previousIndex, event.currentIndex);
    }
    // DO NOT REMOVE. It is called from parent component. See src/app/demo/api-doc/api-doc.component.ts
    /**
     * @param {?} event
     * @return {?}
     */
    apiEvent(event) {
        return this.bindApi(event);
    }
    // tslint:disable:no-big-function cognitive-complexity
    /**
     * @private
     * @param {?} event
     * @return {?}
     */
    bindApi(event) {
        switch (event.type) {
            case API.rowContextMenuClicked:
                this.rowContextMenuPosition = {
                    top: null,
                    left: null,
                    value: null,
                };
                break;
            case API.toolPanelClicked:
                // TODO
                break;
            case API.toggleRowIndex:
                this.collapseRow(event.value);
                break;
            case API.toggleCheckbox:
                this.toggleCheckbox(event.value);
                break;
            case API.setInputValue:
                if (this.config.searchEnabled) {
                    event.value.forEach((/**
                     * @param {?} input
                     * @return {?}
                     */
                    (input) => {
                        /** @type {?} */
                        const element = ((/** @type {?} */ (document.getElementById(`search_${input.key}`))));
                        if (!element) {
                            console.error(`Column '${input.key}' not available in the DOM. Have you misspelled a name?`);
                        }
                        else {
                            element.value = input.value;
                        }
                    }));
                }
                this.onSearch(event.value);
                this.cdr.detectChanges();
                break;
            case API.onGlobalSearch:
                this.onGlobalSearch(event.value);
                this.cdr.detectChanges();
                break;
            case API.setRowClass:
                if (Array.isArray(event.value)) {
                    event.value.forEach((/**
                     * @param {?} val
                     * @return {?}
                     */
                    (val) => this.styleService.setRowClass(val)));
                    break;
                }
                this.styleService.setRowClass(event.value);
                this.cdr.detectChanges();
                break;
            case API.setCellClass:
                if (Array.isArray(event.value)) {
                    event.value.forEach((/**
                     * @param {?} val
                     * @return {?}
                     */
                    (val) => this.styleService.setCellClass(val)));
                    break;
                }
                this.styleService.setCellClass(event.value);
                break;
            case API.setRowStyle:
                if (Array.isArray(event.value)) {
                    event.value.forEach((/**
                     * @param {?} val
                     * @return {?}
                     */
                    (val) => this.styleService.setRowStyle(val)));
                    break;
                }
                this.styleService.setRowStyle(event.value);
                break;
            case API.setCellStyle:
                if (Array.isArray(event.value)) {
                    event.value.forEach((/**
                     * @param {?} val
                     * @return {?}
                     */
                    (val) => this.styleService.setCellStyle(val)));
                    break;
                }
                this.styleService.setCellStyle(event.value);
                break;
            case API.setTableClass:
                this.tableClass = event.value;
                this.cdr.detectChanges();
                break;
            case API.getPaginationTotalItems:
                return this.paginationComponent.paginationDirective.getTotalItems();
            case API.getPaginationCurrentPage:
                return this.paginationComponent.paginationDirective.getCurrent();
            case API.getPaginationLastPage:
                return this.paginationComponent.paginationDirective.getLastPage();
            case API.getNumberOfRowsPerPage:
                return this.paginationComponent.paginationDirective.isLastPage() ?
                    (this.paginationComponent.paginationDirective.getTotalItems() % this.limit) :
                    this.limit;
            case API.setPaginationCurrentPage:
                this.paginationComponent.paginationDirective.setCurrent(event.value);
                break;
            case API.setPaginationRange:
                this.paginationComponent.ranges = event.value;
                break;
            case API.setPaginationPreviousLabel:
                this.paginationComponent.previousLabel = event.value;
                break;
            case API.setPaginationNextLabel:
                this.paginationComponent.nextLabel = event.value;
                break;
            case API.setPaginationDisplayLimit:
                this.paginationComponent.changeLimit(event.value, true);
                break;
            case API.sortBy:
                /** @type {?} */
                const column = { title: '', key: event.value.column, orderBy: event.value.order };
                this.orderBy(column);
                this.cdr.detectChanges();
                break;
            default:
                break;
        }
    }
    /**
     * @private
     * @param {?} key
     * @return {?}
     */
    setColumnOrder(key) {
        switch (this.sortState.get(key)) {
            case '':
            case undefined:
                this.sortState.set(key, 'desc');
                break;
            case 'asc':
                this.config.threeWaySort ?
                    this.sortState.set(key, '') :
                    this.sortState.set(key, 'desc');
                break;
            case 'desc':
                this.sortState.set(key, 'asc');
                break;
        }
        if (this.sortState.size > 1) {
            /** @type {?} */
            const temp = this.sortState.get(key);
            this.sortState.clear();
            this.sortState.set(key, temp);
        }
    }
    /**
     * @param {?} event
     * @param {?} value
     * @return {?}
     */
    emitEvent(event, value) {
        this.event.emit({ event, value });
        if (this.config.persistState) {
            localStorage.setItem(event, JSON.stringify(value));
        }
        if (this.config.logger) {
            // tslint:disable-next-line:no-console
            console.log({ event, value });
        }
    }
}
BaseComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-table',
                providers: [
                    DefaultConfigService,
                    GroupRowsService,
                    StyleService,
                ],
                template: "<div class=\"ngx-container\">\n  <table [id]=\"id\"\n         [ngClass]=\"(tableClass === null || tableClass === '') ? 'ngx-table' : tableClass\"\n         [class.ngx-table__table--tiny]=\"config.tableLayout.style === 'tiny'\"\n         [class.ngx-table__table--normal]=\"config.tableLayout.style === 'normal'\"\n         [class.ngx-table__table--big]=\"config.tableLayout.style === 'big'\"\n         [class.ngx-table__table--borderless]=\"config.tableLayout.borderless\"\n         [class.ngx-table__table--dark]=\"config.tableLayout.theme === 'dark'\"\n         [class.ngx-table__table--hoverable]=\"config.tableLayout.hover\"\n         [class.ngx-table__table--striped]=\"config.tableLayout.striped\"\n         [class.ngx-table__horizontal-scroll]=\"config.horizontalScroll && !isLoading\">\n    <thead\n      [class.ngx-infinite-scroll-viewport-thead]=\"config.infiniteScroll\"\n      table-thead\n      [config]=\"config\"\n      [sortKey]=\"sortKey\"\n      [sortState]=\"sortState\"\n      [selectAllTemplate]=\"selectAllTemplate\"\n      [filtersTemplate]=\"filtersTemplate\"\n      [additionalActionsTemplate]=\"additionalActionsTemplate\"\n      [columns]=\"columns\"\n      (selectAll)=\"onSelectAll()\"\n      (filter)=\"onSearch($event)\"\n      (order)=\"orderBy($event)\"\n      (event)=\"emitEvent($event.event, $event.value)\"\n    >\n    </thead>\n    <tbody *ngIf=\"data && !isLoading && !config.rowReorder\">\n    <ng-container *ngIf=\"rowTemplate\">\n      <ul class=\"ngx-table__table-row-context-menu\"\n          [ngStyle]=\"{'position': 'absolute', 'top': rowContextMenuPosition.top, 'left': rowContextMenuPosition.left }\"\n          *ngIf=\"rowContextMenuPosition.top\">\n        <ng-container\n          [ngTemplateOutlet]=\"rowContextMenu\"\n          [ngTemplateOutletContext]=\"{ $implicit: rowContextMenuPosition.value}\">\n        </ng-container>\n      </ul>\n      <ng-container *ngIf=\"!config.infiniteScroll\">\n        <ng-container *ngFor=\"let row of data | sort:sortBy | search:term:filteredCountSubject | global:globalSearchTerm:filteredCountSubject | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id };\n              let rowIndex = index\">\n          <tr\n            (click)=\"onClick($event, row, '', null, rowIndex)\"\n            #contextMenu\n            (contextmenu)=\"onRowContextMenu($event, row, '', null, rowIndex)\"\n            (dblclick)=\"onDoubleClick($event, row, '', null, rowIndex)\"\n            [class.ngx-table__table-row--selected]=\"rowIndex === selectedRow && !config.selectCell\">\n            <ng-container\n              [ngTemplateOutlet]=\"rowTemplate\"\n              [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\">\n            </ng-container>\n            <td *ngIf=\"config.detailsTemplate\">\n            <span class=\"ngx-icon\"\n                  *ngIf=\"arrowDefinition\"\n                  [ngClass]=\"isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\"\n                  (click)=\"collapseRow(rowIndex)\">\n            </span>\n            </td>\n          </tr>\n          <tr\n            *ngIf=\"(config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) || config.collapseAllRows\">\n            <td [attr.colspan]=\"columns.length + 1\">\n              <ng-container\n                [ngTemplateOutlet]=\"detailsTemplate\"\n                [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex  }\">\n              </ng-container>\n            </td>\n          </tr>\n        </ng-container>\n      </ng-container>\n      <cdk-virtual-scroll-viewport\n        itemSize=\"50\"\n        *ngIf=\"config.infiniteScroll\"\n        class=\"ngx-infinite-scroll-viewport\">\n        <ng-container *cdkVirtualFor=\"let row of data | sort:sortBy | search:term:filteredCountSubject | global:globalSearchTerm:filteredCountSubject;\n              let rowIndex = index\">\n          <tr\n            (click)=\"onClick($event, row, '', null, rowIndex)\"\n            #contextMenu\n            (contextmenu)=\"onRowContextMenu($event, row, '', null, rowIndex)\"\n            (dblclick)=\"onDoubleClick($event, row, '', null, rowIndex)\"\n            [class.ngx-table__table-row--selected]=\"rowIndex === selectedRow && !config.selectCell\">\n            <ng-container\n              [ngTemplateOutlet]=\"rowTemplate\"\n              [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\">\n            </ng-container>\n            <td *ngIf=\"config.detailsTemplate\">\n            <span class=\"ngx-icon\"\n                  *ngIf=\"arrowDefinition\"\n                  [ngClass]=\"isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\"\n                  (click)=\"collapseRow(rowIndex)\">\n            </span>\n            </td>\n          </tr>\n          <tr\n            *ngIf=\"(config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) || config.collapseAllRows\">\n            <td [attr.colspan]=\"columns.length + 1\">\n              <ng-container\n                [ngTemplateOutlet]=\"detailsTemplate\"\n                [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex  }\">\n              </ng-container>\n            </td>\n          </tr>\n        </ng-container>\n      </cdk-virtual-scroll-viewport>\n    </ng-container>\n    <ng-container *ngIf=\"!rowTemplate && !config.groupRows\">\n      <ul class=\"ngx-table__table-row-context-menu\"\n          [ngStyle]=\"{'position': 'absolute', 'top': rowContextMenuPosition.top, 'left': rowContextMenuPosition.left }\"\n          *ngIf=\"rowContextMenuPosition.top\">\n        <ng-container\n          [ngTemplateOutlet]=\"rowContextMenu\"\n          [ngTemplateOutletContext]=\"{ $implicit: rowContextMenuPosition.value}\">\n        </ng-container>\n      </ul>\n      <ng-container *ngIf=\"!config.infiniteScroll\">\n        <ng-container\n          *ngFor=\"let row of data | sort:sortBy | search:term:filteredCountSubject | global:globalSearchTerm:filteredCountSubject | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id };\n                  let rowIndex = index\">\n          <tr [class.ngx-table__table-row--selected]=\"rowIndex === selectedRow && !config.selectCell\">\n            <td *ngIf=\"config.checkboxes\">\n              <label class=\"ngx-form-checkbox\">\n                <input type=\"checkbox\"\n                       id=\"checkbox-{{rowIndex}}\"\n                       [checked]=\"isSelected || selectedCheckboxes.has(rowIndex)\"\n                       (change)=\"onCheckboxSelect($event, row, rowIndex)\">\n                <em class=\"ngx-form-icon\"></em>\n              </label>\n            </td>\n            <td *ngIf=\"config.radio\">\n              <label>\n                <input type=\"radio\"\n                       id=\"radio-{{rowIndex}}\"\n                       name=\"radio\"\n                       (change)=\"onRadioSelect($event, row, rowIndex)\">\n              </label>\n            </td>\n            <ng-container *ngFor=\"let column of columns; let colIndex = index\">\n              <td (click)=\"onClick($event, row, column.key, colIndex, rowIndex)\"\n                  #contextMenu\n                  (contextmenu)=\"onRowContextMenu($event, row, column.key, colIndex, rowIndex)\"\n                  (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, rowIndex)\"\n                  [class.pinned-left]=\"column.pinned\"\n                  [ngClass]=\"column.cssClass ? column.cssClass.name : ''\"\n                  [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\n                  [class.ngx-table__table-col--selected]=\"colIndex === selectedCol && !config.selectCell\"\n                  [class.ngx-table__table-cell--selected]=\"colIndex === selectedCol && rowIndex === selectedRow && !config.selectCol && !config.selectRow\"\n              >\n                <div *ngIf=\"!column.cellTemplate\">{{ row | render:column.key }}</div>\n                <ng-container\n                  *ngIf=\"column.cellTemplate\"\n                  [ngTemplateOutlet]=\"column.cellTemplate\"\n                  [ngTemplateOutletContext]=\"{ $implicit: row, rowIndex: rowIndex }\">\n                </ng-container>\n              </td>\n            </ng-container>\n            <td *ngIf=\"config.additionalActions || config.detailsTemplate\">\n            <span class=\"ngx-icon\"\n                  *ngIf=\"arrowDefinition\"\n                  [ngClass]=\"isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\"\n                  (click)=\"collapseRow(rowIndex)\">\n            </span>\n            </td>\n          </tr>\n          <tr\n            *ngIf=\"(config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) || config.collapseAllRows\">\n            <td *ngIf=\"config.checkboxes || config.radio\"></td>\n            <td [attr.colspan]=\"columns.length + 1\">\n              <ng-container\n                [ngTemplateOutlet]=\"detailsTemplate\"\n                [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\">\n              </ng-container>\n            </td>\n          </tr>\n        </ng-container>\n      </ng-container>\n      <!-- infinite scroll -->\n      <cdk-virtual-scroll-viewport\n        itemSize=\"50\"\n        *ngIf=\"config.infiniteScroll\"\n        class=\"ngx-infinite-scroll-viewport\">\n        <ng-container\n          *cdkVirtualFor=\"let row of data | sort:sortBy | search:term:filteredCountSubject | global:globalSearchTerm:filteredCountSubject;\n                  let rowIndex = index\">\n          <tr [class.ngx-table__table-row--selected]=\"rowIndex === selectedRow && !config.selectCell\">\n            <td *ngIf=\"config.checkboxes\">\n              <label class=\"ngx-form-checkbox\">\n                <input type=\"checkbox\"\n                       id=\"checkbox-infinite-scroll-{{rowIndex}}\"\n                       [checked]=\"isSelected || selectedCheckboxes.has(rowIndex)\"\n                       (change)=\"onCheckboxSelect($event, row, rowIndex)\">\n                <em class=\"ngx-form-icon\"></em>\n              </label>\n            </td>\n            <td *ngIf=\"config.radio\">\n              <label>\n                <input type=\"radio\"\n                       id=\"radio-infinite-scroll-{{rowIndex}}\"\n                       name=\"radio\"\n                       (change)=\"onRadioSelect($event, row, rowIndex)\">\n              </label>\n            </td>\n            <ng-container *ngFor=\"let column of columns; let colIndex = index\">\n              <td (click)=\"onClick($event, row, column.key, colIndex, rowIndex)\"\n                  #contextMenu\n                  (contextmenu)=\"onRowContextMenu($event, row, column.key, colIndex, rowIndex)\"\n                  (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, rowIndex)\"\n                  [class.pinned-left]=\"column.pinned\"\n                  [ngClass]=\"column.cssClass ? column.cssClass.name : ''\"\n                  [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\n                  [class.ngx-table__table-col--selected]=\"colIndex === selectedCol && !config.selectCell\"\n                  [class.ngx-table__table-cell--selected]=\"colIndex === selectedCol && rowIndex === selectedRow && !config.selectCol && !config.selectRow\"\n              >\n                <div *ngIf=\"!column.cellTemplate\">{{ row | render:column.key }}</div>\n                <ng-container\n                  *ngIf=\"column.cellTemplate\"\n                  [ngTemplateOutlet]=\"column.cellTemplate\"\n                  [ngTemplateOutletContext]=\"{ $implicit: row, rowIndex: rowIndex }\">\n                </ng-container>\n              </td>\n            </ng-container>\n            <td *ngIf=\"config.additionalActions || config.detailsTemplate\">\n            <span class=\"ngx-icon\"\n                  *ngIf=\"arrowDefinition\"\n                  [ngClass]=\"isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\"\n                  (click)=\"collapseRow(rowIndex)\">\n            </span>\n            </td>\n          </tr>\n          <tr\n            *ngIf=\"(config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) || config.collapseAllRows\">\n            <td *ngIf=\"config.checkboxes || config.radio\"></td>\n            <td [attr.colspan]=\"columns.length + 1\">\n              <ng-container\n                [ngTemplateOutlet]=\"detailsTemplate\"\n                [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\">\n              </ng-container>\n            </td>\n          </tr>\n        </ng-container>\n      </cdk-virtual-scroll-viewport>\n    </ng-container>\n    <ng-container *ngIf=\"!rowTemplate && config.groupRows\">\n      <ng-container\n        *ngFor=\"let group of grouped | sort:sortBy:config | search:term:filteredCountSubject:config | global:globalSearchTerm:filteredCountSubject | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id };\n        let rowIndex = index\">\n        <tr>\n          <ng-container *ngIf=\"!groupRowsHeaderTemplate\">\n            <td [attr.colspan]=\"columns.length\">\n              <div>{{group[0][groupRowsBy]}} ({{group.length}})</div>\n            </td>\n          </ng-container>\n          <ng-container\n            *ngIf=\"groupRowsHeaderTemplate\"\n            [ngTemplateOutlet]=\"groupRowsHeaderTemplate\"\n            [ngTemplateOutletContext]=\"{\n              total: group.length,\n              key: groupRowsBy,\n              value: group[0] ? group[0][groupRowsBy] : '',\n              group: group,\n              index: rowIndex\n            }\">\n          </ng-container>\n          <td>\n            <span class=\"ngx-icon\"\n                  *ngIf=\"arrowDefinition\"\n                  [ngClass]=\"isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\"\n                  (click)=\"collapseRow(rowIndex)\">\n            </span>\n          </td>\n        </tr>\n        <ng-container *ngIf=\"selectedDetailsTemplateRowId.has(rowIndex)\">\n          <tr *ngFor=\"let row of group\">\n            <td *ngFor=\"let column of columns\">\n              {{ row | render:column.key }}\n              <!-- TODO allow users to add groupRowsTemplateRef -->\n            </td>\n            <td></td>\n          </tr>\n        </ng-container>\n      </ng-container>\n    </ng-container>\n    </tbody>\n    <tbody *ngIf=\"data && !config.isLoading && config.rowReorder\"\n           class=\"ngx-draggable-row-area\"\n           cdkDropList\n           (cdkDropListDropped)=\"onDrop($event)\">\n    <ng-container *ngIf=\"!rowTemplate && !config.groupRows\">\n      <ng-container\n        *ngFor=\"let row of data | sort:sortBy | search:term:filteredCountSubject | global:globalSearchTerm:filteredCountSubject | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id };\n                  let rowIndex = index\">\n        <tr class=\"ngx-draggable-row\" cdkDrag cdkDragLockAxis=\"y\">\n          <td *ngIf=\"config.checkboxes\">\n            <label class=\"ngx-form-checkbox\">\n              <input type=\"checkbox\"\n                     id=\"checkbox-draggable-{{rowIndex}}\"\n                     [checked]=\"isSelected || selectedCheckboxes.has(rowIndex)\"\n                     (change)=\"onCheckboxSelect($event, row, rowIndex)\">\n              <em class=\"ngx-form-icon\"></em>\n            </label>\n          </td>\n          <td *ngIf=\"config.radio\">\n            <label>\n              <input type=\"radio\"\n                     id=\"radio-draggable-{{rowIndex}}\"\n                     name=\"radio\"\n                     (change)=\"onRadioSelect($event, row, rowIndex)\">\n            </label>\n          </td>\n          <ng-container *ngFor=\"let column of columns; let colIndex = index\">\n            <td (click)=\"onClick($event, row, column.key, colIndex, rowIndex)\"\n                (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, rowIndex)\"\n                [class.ngx-table__table-col--selected]=\"colIndex === selectedCol && !config.selectCell\"\n                [class.ngx-table__table-cell--selected]=\"colIndex === selectedCol && rowIndex === selectedRow && !config.selectCol && !config.selectRow\"\n            >\n              <div>{{ row | render:column.key }}</div>\n            </td>\n          </ng-container>\n        </tr>\n      </ng-container>\n    </ng-container>\n    </tbody>\n    <tbody *ngIf=\"filterCount === 0\">\n    <tr class=\"ngx-table__body-empty\">\n      <ng-container\n        *ngIf=\"noResultsTemplate\"\n        [ngTemplateOutlet]=\"noResultsTemplate\">\n      </ng-container>\n      <td [attr.colspan]=\"columns && columns.length + 1\" *ngIf=\"!noResultsTemplate\">\n        <div class=\"ngx-table__table-no-results\">\n          No results\n        </div>\n      </td>\n    </tr>\n    </tbody>\n    <tbody *ngIf=\"isLoading\">\n    <tr class=\"ngx-table__body-loading\">\n      <ng-container\n        *ngIf=\"loadingTemplate\"\n        [ngTemplateOutlet]=\"loadingTemplate\">\n      </ng-container>\n      <td [attr.colspan]=\"columns && columns.length + 1\" *ngIf=\"!loadingTemplate\">\n        <div [style.height]=\"loadingHeight\"\n             class=\"ngx-table__table-loader-wrapper\">\n          <div class=\"ngx-table__table-loader\"></div>\n        </div>\n      </td>\n    </tr>\n    </tbody>\n    <tfoot *ngIf=\"summaryTemplate\">\n    <tr>\n      <ng-container\n        [ngTemplateOutlet]=\"summaryTemplate\"\n        [ngTemplateOutletContext]=\"{ total: data.length, limit: limit, page: page  }\">\n      </ng-container>\n    </tr>\n    </tfoot>\n  </table>\n  <pagination\n    [attr.id]=\"'pagination' + id\"\n    [id]=\"id\"\n    #paginationComponent\n    [config]=\"config\"\n    [pagination]=\"pagination\"\n    (updateRange)=\"onPagination($event)\">\n  </pagination>\n</div>\n",
                changeDetection: ChangeDetectionStrategy.OnPush
            }] }
];
/** @nocollapse */
BaseComponent.ctorParameters = () => [
    { type: ChangeDetectorRef },
    { type: ScrollDispatcher },
    { type: StyleService }
];
BaseComponent.propDecorators = {
    configuration: [{ type: Input }],
    data: [{ type: Input }],
    pagination: [{ type: Input }],
    groupRowsBy: [{ type: Input }],
    id: [{ type: Input }],
    toggleRowIndex: [{ type: Input }],
    detailsTemplate: [{ type: Input }],
    summaryTemplate: [{ type: Input }],
    groupRowsHeaderTemplate: [{ type: Input }],
    filtersTemplate: [{ type: Input }],
    selectAllTemplate: [{ type: Input }],
    noResultsTemplate: [{ type: Input }],
    loadingTemplate: [{ type: Input }],
    additionalActionsTemplate: [{ type: Input }],
    rowContextMenu: [{ type: Input }],
    columns: [{ type: Input }],
    event: [{ type: Output }],
    rowTemplate: [{ type: ContentChild, args: [TemplateRef, { static: true },] }],
    paginationComponent: [{ type: ViewChild, args: ['paginationComponent', { static: false },] }],
    contextMenu: [{ type: ViewChild, args: ['contextMenu', { static: false },] }],
    viewPort: [{ type: ViewChild, args: [CdkVirtualScrollViewport, { static: false },] }],
    onContextMenuClick: [{ type: HostListener, args: ['document:click', ['$event.target'],] }]
};
if (false) {
    /**
     * @type {?}
     * @private
     */
    BaseComponent.prototype.unsubscribe;
    /** @type {?} */
    BaseComponent.prototype.selectedRow;
    /** @type {?} */
    BaseComponent.prototype.selectedCol;
    /** @type {?} */
    BaseComponent.prototype.term;
    /** @type {?} */
    BaseComponent.prototype.filterCount;
    /** @type {?} */
    BaseComponent.prototype.filteredCountSubject;
    /** @type {?} */
    BaseComponent.prototype.subscription;
    /** @type {?} */
    BaseComponent.prototype.tableClass;
    /** @type {?} */
    BaseComponent.prototype.globalSearchTerm;
    /** @type {?} */
    BaseComponent.prototype.grouped;
    /** @type {?} */
    BaseComponent.prototype.isSelected;
    /** @type {?} */
    BaseComponent.prototype.page;
    /** @type {?} */
    BaseComponent.prototype.count;
    /** @type {?} */
    BaseComponent.prototype.sortState;
    /** @type {?} */
    BaseComponent.prototype.sortKey;
    /** @type {?} */
    BaseComponent.prototype.rowContextMenuPosition;
    /** @type {?} */
    BaseComponent.prototype.limit;
    /** @type {?} */
    BaseComponent.prototype.sortBy;
    /** @type {?} */
    BaseComponent.prototype.selectedDetailsTemplateRowId;
    /** @type {?} */
    BaseComponent.prototype.selectedCheckboxes;
    /** @type {?} */
    BaseComponent.prototype.loadingHeight;
    /** @type {?} */
    BaseComponent.prototype.config;
    /** @type {?} */
    BaseComponent.prototype.configuration;
    /** @type {?} */
    BaseComponent.prototype.data;
    /** @type {?} */
    BaseComponent.prototype.pagination;
    /** @type {?} */
    BaseComponent.prototype.groupRowsBy;
    /** @type {?} */
    BaseComponent.prototype.id;
    /** @type {?} */
    BaseComponent.prototype.toggleRowIndex;
    /** @type {?} */
    BaseComponent.prototype.detailsTemplate;
    /** @type {?} */
    BaseComponent.prototype.summaryTemplate;
    /** @type {?} */
    BaseComponent.prototype.groupRowsHeaderTemplate;
    /** @type {?} */
    BaseComponent.prototype.filtersTemplate;
    /** @type {?} */
    BaseComponent.prototype.selectAllTemplate;
    /** @type {?} */
    BaseComponent.prototype.noResultsTemplate;
    /** @type {?} */
    BaseComponent.prototype.loadingTemplate;
    /** @type {?} */
    BaseComponent.prototype.additionalActionsTemplate;
    /** @type {?} */
    BaseComponent.prototype.rowContextMenu;
    /** @type {?} */
    BaseComponent.prototype.columns;
    /** @type {?} */
    BaseComponent.prototype.event;
    /** @type {?} */
    BaseComponent.prototype.rowTemplate;
    /**
     * @type {?}
     * @private
     */
    BaseComponent.prototype.paginationComponent;
    /** @type {?} */
    BaseComponent.prototype.contextMenu;
    /** @type {?} */
    BaseComponent.prototype.viewPort;
    /**
     * @type {?}
     * @private
     */
    BaseComponent.prototype.cdr;
    /**
     * @type {?}
     * @private
     */
    BaseComponent.prototype.scrollDispatcher;
    /** @type {?} */
    BaseComponent.prototype.styleService;
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class HeaderComponent {
    constructor() {
        this.update = new EventEmitter();
    }
    /**
     * @param {?} key
     * @return {?}
     */
    unifyKey(key) {
        return key.replace('.', '_');
    }
    /**
     * @param {?} input
     * @return {?}
     */
    onSearch(input) {
        this.update.emit([
            { value: input.value, key: this.column.key },
        ]);
    }
}
HeaderComponent.decorators = [
    { type: Component, args: [{
                selector: 'table-header',
                template: "<label for=\"search_{{ unifyKey(column.key) }}\">\n  <input type=\"text\"\n         id=\"search_{{ unifyKey(column.key) }}\"\n         aria-label=\"Search\"\n         placeholder=\"{{ column.placeholder ? column.placeholder : column.title }}\"\n         class=\"ngx-table__header-search\"\n         #input\n         (input)=\"onSearch(input)\"\n  >\n</label>\n"
            }] }
];
HeaderComponent.propDecorators = {
    column: [{ type: Input }],
    update: [{ type: Output }]
};
if (false) {
    /** @type {?} */
    HeaderComponent.prototype.column;
    /** @type {?} */
    HeaderComponent.prototype.update;
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class GlobalSearchPipe {
    /**
     * @param {?} array
     * @param {?} filter
     * @param {?} filteredCountSubject
     * @return {?}
     */
    transform(array, filter, filteredCountSubject) {
        filteredCountSubject.next(0);
        if (typeof array === 'undefined') {
            return;
        }
        if (typeof filter === 'undefined' || Object.keys(filter).length === 0 || filter === '') {
            filteredCountSubject.next(array.length);
            return array;
        }
        /** @type {?} */
        const arr = array.filter((/**
         * @param {?} row
         * @return {?}
         */
        (row) => {
            /** @type {?} */
            const element = JSON.stringify(Object.values(row));
            /** @type {?} */
            const strings = filter.split(',');
            return strings.some((/**
             * @param {?} string
             * @return {?}
             */
            (string) => element.toLocaleLowerCase().indexOf(string.trim().toLocaleLowerCase()) > -1));
        }));
        filteredCountSubject.next(arr.length);
        return arr;
    }
}
GlobalSearchPipe.decorators = [
    { type: Pipe, args: [{
                name: 'global',
            },] }
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class FiltersService {
    /**
     * @param {?} p
     * @param {?} o
     * @return {?}
     */
    static getPath(p, o) {
        // https://github.com/dherges/ng-packagr/issues/696
        /* tslint:disable-next-line */
        /** @type {?} */
        const result = p.reduce((/**
         * @param {?} xs
         * @param {?} x
         * @return {?}
         */
        (xs, x) => (xs && typeof xs[x] !== 'undefined') ? xs[x] : null), o);
        return result;
    }
}
FiltersService.decorators = [
    { type: Injectable }
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class RenderPipe {
    /**
     * @param {?} row
     * @param {?} key
     * @return {?}
     */
    transform(row, key) {
        /** @type {?} */
        const split = key.split('.');
        return FiltersService.getPath(split, row);
    }
}
RenderPipe.decorators = [
    { type: Pipe, args: [{
                name: 'render',
            },] }
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class SearchPipe {
    constructor() {
        this.filters = {};
    }
    /**
     * @param {?} array
     * @param {?} filter
     * @param {?} filteredCountSubject
     * @param {?=} config
     * @return {?}
     */
    transform(array, filter, filteredCountSubject, config) {
        filteredCountSubject.next(0);
        if (typeof array === 'undefined') {
            return;
        }
        if (typeof filter === 'undefined') {
            filteredCountSubject.next(array.length);
            return array;
        }
        filter.forEach((/**
         * @param {?} f
         * @return {?}
         */
        (f) => {
            this.filters[f.key] = f.value.toString().toLocaleLowerCase();
            if (Object.keys(f).length === 0 || f.value === '') {
                delete this.filters[f.key];
            }
        }));
        if (config && config.groupRows) {
            return array.map((/**
             * @param {?} arr
             * @return {?}
             */
            (arr) => this.filterGroup(arr, filteredCountSubject)));
        }
        return this.filterGroup(array, filteredCountSubject);
    }
    /**
     * @private
     * @param {?} array
     * @param {?} filteredCountSubject
     * @return {?}
     */
    filterGroup(array, filteredCountSubject) {
        /** @type {?} */
        const arr = array.filter((/**
         * @param {?} obj
         * @return {?}
         */
        (obj) => {
            return Object.keys(this.filters).every((/**
             * @param {?} c
             * @return {?}
             */
            (c) => {
                /** @type {?} */
                const split = c.split('.');
                /** @type {?} */
                const val = FiltersService.getPath(split, obj);
                /** @type {?} */
                const element = (typeof val === 'object') ? JSON.stringify(val) : val.toString().toLocaleLowerCase();
                /** @type {?} */
                const strings = this.filters[c].split(',');
                return strings.some((/**
                 * @param {?} string
                 * @return {?}
                 */
                (string) => element.indexOf(string.trim()) > -1));
            }));
        }));
        filteredCountSubject.next(arr.length);
        return arr;
    }
}
SearchPipe.decorators = [
    { type: Pipe, args: [{
                name: 'search',
            },] }
];
if (false) {
    /**
     * @type {?}
     * @private
     */
    SearchPipe.prototype.filters;
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class SortPipe {
    constructor() {
        this.defaultArray = [];
    }
    /**
     * @private
     * @param {?} aV
     * @param {?} bV
     * @return {?}
     */
    static isNaN(aV, bV) {
        return (isNaN(parseFloat(aV)) || !isFinite(aV)) || (isNaN(parseFloat(bV)) || !isFinite(bV));
    }
    /**
     * @private
     * @param {?} a
     * @param {?} b
     * @param {?} key
     * @return {?}
     */
    static compare(a, b, key) {
        /** @type {?} */
        const split = key.split('.');
        /** @type {?} */
        const aPath = FiltersService.getPath(split, a);
        /** @type {?} */
        const bPath = FiltersService.getPath(split, b);
        /** @type {?} */
        const aValue = (aPath + '').toLowerCase();
        /** @type {?} */
        const bValue = (bPath + '').toLowerCase();
        if (SortPipe.isNaN(aPath, bPath)) {
            return aValue.localeCompare(bValue);
        }
        else {
            if (parseFloat(aPath) < parseFloat(bPath)) {
                return -1;
            }
            if (parseFloat(aPath) > parseFloat(bPath)) {
                return 1;
            }
        }
        return 0;
    }
    /**
     * @param {?} array
     * @param {?} filter
     * @param {?=} config
     * @return {?}
     */
    transform(array, filter, config) {
        if (this.defaultArray.length === 0) {
            this.defaultArray = array;
        }
        if (!filter.key || filter.key === '') {
            return array;
        }
        if (filter.order === '') {
            return this.defaultArray;
        }
        if (filter.order === 'asc') {
            return this.sortAsc(array, filter, config);
        }
        else {
            return this.sortDesc(array, filter, config);
        }
    }
    /**
     * @private
     * @param {?} array
     * @param {?} filter
     * @param {?=} config
     * @return {?}
     */
    sortAsc(array, filter, config) {
        if (config && config.groupRows) {
            return array.map((/**
             * @param {?} arr
             * @return {?}
             */
            (arr) => arr.sort((/**
             * @param {?} a
             * @param {?} b
             * @return {?}
             */
            (a, b) => SortPipe.compare(a, b, filter.key)))));
        }
        return array.sort((/**
         * @param {?} a
         * @param {?} b
         * @return {?}
         */
        (a, b) => SortPipe.compare(a, b, filter.key)));
    }
    /**
     * @private
     * @param {?} array
     * @param {?} filter
     * @param {?=} config
     * @return {?}
     */
    sortDesc(array, filter, config) {
        if (config && config.groupRows) {
            return array.map((/**
             * @param {?} arr
             * @return {?}
             */
            (arr) => arr.sort((/**
             * @param {?} a
             * @param {?} b
             * @return {?}
             */
            (a, b) => SortPipe.compare(b, a, filter.key)))));
        }
        return array.sort((/**
         * @param {?} a
         * @param {?} b
         * @return {?}
         */
        (a, b) => SortPipe.compare(b, a, filter.key)));
    }
}
SortPipe.decorators = [
    { type: Pipe, args: [{
                name: 'sort',
            },] }
];
if (false) {
    /**
     * @type {?}
     * @private
     */
    SortPipe.prototype.defaultArray;
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class TableTHeadComponent {
    /**
     * @param {?} styleService
     */
    constructor(styleService) {
        this.styleService = styleService;
        this.menuActive = false;
        this.openedHeaderActionTemplate = null;
        this.onSelectAllBinded = this.onSelectAll.bind(this);
        this.filter = new EventEmitter();
        this.order = new EventEmitter();
        this.selectAll = new EventEmitter();
        this.event = new EventEmitter();
    }
    /**
     * @param {?} targetElement
     * @return {?}
     */
    onClick(targetElement) {
        if (this.additionalActionMenu && !this.additionalActionMenu.nativeElement.contains(targetElement)) {
            this.menuActive = false;
        }
    }
    /**
     * @param {?} column
     * @return {?}
     */
    getColumnDefinition(column) {
        return column.searchEnabled || typeof column.searchEnabled === 'undefined';
    }
    /**
     * @param {?} column
     * @return {?}
     */
    orderBy(column) {
        this.order.emit(column);
    }
    /**
     * @param {?} column
     * @return {?}
     */
    isOrderEnabled(column) {
        /** @type {?} */
        const columnOrderEnabled = column.orderEnabled === undefined ? true : !!column.orderEnabled;
        return this.config.orderEnabled && columnOrderEnabled;
    }
    /**
     * @param {?} event
     * @return {?}
     */
    columnDrop(event) {
        moveItemInArray(this.columns, event.previousIndex, event.currentIndex);
    }
    /**
     * @param {?} $event
     * @return {?}
     */
    onSearch($event) {
        this.filter.emit($event);
    }
    /**
     * @param {?} column
     * @return {?}
     */
    getColumnWidth(column) {
        if (column.width) {
            return column.width;
        }
        return this.config.fixedColumnWidth ? 100 / this.columns.length + '%' : null;
    }
    /**
     * @return {?}
     */
    onSelectAll() {
        this.selectAll.emit();
    }
    /**
     * @param {?} event
     * @param {?} th
     * @return {?}
     */
    onMouseDown(event, th) {
        if (!this.config.resizeColumn) {
            return;
        }
        this.th = th;
        this.startOffset = th.offsetWidth - event.pageX;
        this.event.emit({
            event: Event.onColumnResizeMouseDown,
            value: event,
        });
    }
    /**
     * @param {?} event
     * @return {?}
     */
    onMouseMove(event) {
        if (!this.config.resizeColumn) {
            return;
        }
        if (this.th && this.th.style) {
            this.th.style.width = this.startOffset + event.pageX + 'px';
            this.th.style.cursor = 'col-resize';
            this.th.style['user-select'] = 'none';
        }
    }
    /**
     * @param {?} event
     * @return {?}
     */
    onMouseUp(event) {
        if (!this.config.resizeColumn) {
            return;
        }
        this.event.emit({
            event: Event.onColumnResizeMouseUp,
            value: event,
        });
        this.th.style.cursor = 'default';
        this.th = undefined;
    }
    /**
     * @param {?} column
     * @return {?}
     */
    showHeaderActionTemplateMenu(column) {
        if (!column.headerActionTemplate) {
            console.error('Column [headerActionTemplate] property not defined');
        }
        if (this.openedHeaderActionTemplate === column.key) {
            this.openedHeaderActionTemplate = null;
            return;
        }
        this.openedHeaderActionTemplate = column.key;
    }
    /**
     * @return {?}
     */
    showMenu() {
        if (!this.additionalActionsTemplate) {
            console.error('[additionalActionsTemplate] property not defined');
        }
        this.menuActive = !this.menuActive;
    }
}
TableTHeadComponent.decorators = [
    { type: Component, args: [{
                selector: '[table-thead]',
                template: "<tr class=\"ngx-table__header\" *ngIf=\"config.headerEnabled && !config.columnReorder\">\n  <th *ngIf=\"config.checkboxes || config.radio\" [style.width]=\"'3%'\">\n    <ng-container\n      *ngIf=\"selectAllTemplate && config.checkboxes\"\n      [ngTemplateOutlet]=\"selectAllTemplate\"\n      [ngTemplateOutletContext]=\"{ $implicit: onSelectAllBinded }\">\n    </ng-container>\n    <label class=\"ngx-form-checkbox\"\n           for=\"selectAllCheckboxes\"\n           *ngIf=\"!selectAllTemplate && config.checkboxes\">\n      <input type=\"checkbox\" id=\"selectAllCheckboxes\" (change)=\"onSelectAll()\">\n      <em class=\"ngx-form-icon\" id=\"selectAllCheckbox\"></em>\n    </label>\n  </th>\n  <ng-container *ngFor=\"let column of columns; let colIndex = index; let last = last\">\n    <th class=\"ngx-table__header-cell\"\n        [class.pinned-left]=\"column.pinned\"\n        [ngClass]=\"column.cssClass && column.cssClass.includeHeader ? column.cssClass.name : ''\"\n        [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\n        #th\n        [style.width]=\"getColumnWidth(column)\"\n        (mousedown)=\"onMouseDown($event, th)\"\n        (mouseup)=\"onMouseUp($event)\"\n        (mousemove)=\"onMouseMove($event)\">\n      <div (click)=\"orderBy(column)\" style=\"display: inline\" [class.pointer]=\"isOrderEnabled(column)\">\n        <div class=\"ngx-table__header-title\">{{ column.title }}<span>&nbsp;</span>\n          <em class=\"ngx-icon ngx-icon-pin\" *ngIf=\"column.pinned\"></em>\n          <div [style.display]=\"config.orderEnabled ? 'inline' : 'none' \">\n            <em *ngIf=\"sortKey === column.key && this.sortState.get(sortKey) === 'asc'\"\n               class=\"ngx-icon ngx-icon-arrow-up\">\n            </em>\n            <em *ngIf=\"sortKey === column.key && this.sortState.get(sortKey) === 'desc'\"\n               class=\"ngx-icon ngx-icon-arrow-down\">\n            </em>\n          </div>\n        </div>\n      </div>\n      <div class=\"ngx-dropdown\"\n           *ngIf=\"!!column.headerActionTemplate\">\n        <a class=\"ngx-btn ngx-btn-link\" (click)=\"showHeaderActionTemplateMenu(column)\">\n          <span class=\"ngx-icon ngx-icon-more\"></span>\n        </a>\n        <div class=\"ngx-menu ngx-table__table-menu\"\n            *ngIf=\"column.key === openedHeaderActionTemplate\">\n          <ng-container\n            [ngTemplateOutlet]=\"column.headerActionTemplate\">\n          </ng-container>\n        </div>\n      </div>\n      <div class=\"ngx-table__column-resizer\" *ngIf=\"config.resizeColumn && !last\"></div>\n    </th>\n  </ng-container>\n  <th *ngIf=\"config.additionalActions || config.detailsTemplate || config.collapseAllRows || config.groupRows\"\n      class=\"ngx-table__header-cell-additional-actions\">\n    <div class=\"ngx-dropdown\"\n         #additionalActionMenu\n         *ngIf=\"config.additionalActions\">\n      <a class=\"ngx-btn ngx-btn-link\" (click)=\"showMenu()\">\n        <span class=\"ngx-icon ngx-icon-menu\"></span>\n      </a>\n      <ul class=\"ngx-menu ngx-table__table-menu\"\n          *ngIf=\"menuActive\">\n        <ng-container\n          *ngIf=\"additionalActionsTemplate\"\n          [ngTemplateOutlet]=\"additionalActionsTemplate\">\n        </ng-container>\n      </ul>\n    </div>\n  </th>\n</tr>\n<tr class=\"ngx-table__header ngx-table__header--draggable\"\n    *ngIf=\"config.headerEnabled && config.columnReorder\"\n    cdkDropList\n    cdkDropListOrientation=\"horizontal\"\n    (cdkDropListDropped)=\"columnDrop($event)\"\n>\n  <th [style.width]=\"'3%'\">\n    <ng-container\n      *ngIf=\"selectAllTemplate && config.checkboxes\"\n      [ngTemplateOutlet]=\"selectAllTemplate\"\n      [ngTemplateOutletContext]=\"{ $implicit: onSelectAllBinded }\">\n    </ng-container>\n    <label class=\"ngx-form-checkbox\"\n           for=\"selectAllCheckboxes\"\n           *ngIf=\"!selectAllTemplate && config.checkboxes\">\n      <input type=\"checkbox\" id=\"selectAllCheckboxesDrag\" (change)=\"onSelectAll()\">\n      <em class=\"ngx-form-icon\" id=\"selectAllCheckboxDrag\"></em>\n    </label>\n  </th>\n  <ng-container *ngFor=\"let column of columns; let colIndex = index; let last = last\">\n    <th class=\"ngx-table__header-cell ngx-table__header-cell--draggable\"\n        cdkDragLockAxis=\"x\"\n        cdkDrag\n        [class.pinned-left]=\"column.pinned\"\n        [ngClass]=\"column.cssClass && column.cssClass.includeHeader ? column.cssClass.name : ''\"\n        [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\n        #th\n        [style.width]=\"getColumnWidth(column)\"\n        (mousedown)=\"onMouseDown($event, th)\"\n        (mouseup)=\"onMouseUp($event)\"\n        (mousemove)=\"onMouseMove($event)\">\n      <div (click)=\"orderBy(column)\" style=\"display: inline\"\n           cdkDragHandle\n           [class.pointer]=\"isOrderEnabled(column)\">\n        <div class=\"ngx-table__header-title\">{{ column.title }}<span>&nbsp;</span>\n          <em class=\"ngx-icon ngx-icon-pin\" *ngIf=\"column.pinned\"></em>\n          <div [style.display]=\"config.orderEnabled ? 'inline' : 'none' \">\n            <em *ngIf=\"sortKey === column.key && this.sortState.get(sortKey) === 'asc'\"\n                class=\"ngx-icon ngx-icon-arrow-up\">\n            </em>\n            <em *ngIf=\"sortKey === column.key && this.sortState.get(sortKey) === 'desc'\"\n                class=\"ngx-icon ngx-icon-arrow-down\">\n            </em>\n          </div>\n        </div>\n      </div>\n      <div class=\"ngx-dropdown\"\n           *ngIf=\"!!column.headerActionTemplate\">\n        <a class=\"ngx-btn ngx-btn-link\" (click)=\"showHeaderActionTemplateMenu(column)\">\n          <span class=\"ngx-icon ngx-icon-more\"></span>\n        </a>\n        <div class=\"ngx-menu ngx-table__table-menu\"\n             *ngIf=\"column.key === openedHeaderActionTemplate\">\n          <ng-container\n            [ngTemplateOutlet]=\"column.headerActionTemplate\">\n          </ng-container>\n        </div>\n      </div>\n      <div class=\"ngx-table__column-resizer\" *ngIf=\"config.resizeColumn && !last\"></div>\n    </th>\n  </ng-container>\n  <th *ngIf=\"config.additionalActions || config.detailsTemplate || config.collapseAllRows || config.groupRows\"\n      class=\"ngx-table__header-cell-additional-actions\">\n    <div class=\"ngx-dropdown\"\n         #additionalActionMenu\n         *ngIf=\"config.additionalActions\">\n      <a class=\"ngx-btn ngx-btn-link\" (click)=\"showMenu()\">\n        <span class=\"ngx-icon ngx-icon-menu\"></span>\n      </a>\n      <ul class=\"ngx-menu ngx-table__table-menu\"\n          *ngIf=\"menuActive\">\n        <ng-container\n          *ngIf=\"additionalActionsTemplate\"\n          [ngTemplateOutlet]=\"additionalActionsTemplate\">\n        </ng-container>\n      </ul>\n    </div>\n  </th>\n</tr>\n<tr *ngIf=\"config.searchEnabled && !filtersTemplate\"\n    class=\"ngx-table__sort-header\">\n  <th *ngIf=\"config.checkboxes || config.radio\"></th>\n  <ng-container *ngFor=\"let column of columns; let colIndex = index\">\n    <th\n      [ngClass]=\"column.cssClass && column.cssClass.includeHeader ? column.cssClass.name : ''\"\n      [class.pinned-left]=\"column.pinned\"\n      [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\">\n      <table-header\n        *ngIf=\"getColumnDefinition(column)\"\n        (update)=\"onSearch($event)\"\n        [column]=\"column\">\n      </table-header>\n    </th>\n  </ng-container>\n  <th *ngIf=\"config.additionalActions || config.detailsTemplate\"></th>\n</tr>\n<ng-container *ngIf=\"filtersTemplate\">\n  <tr>\n    <ng-container [ngTemplateOutlet]=\"filtersTemplate\">\n    </ng-container>\n  </tr>\n</ng-container>\n",
                providers: [StyleService],
                styles: [`
    .cdk-drag-preview {
      text-align: left;
      padding-top: 9px;
      padding-left: 4px;
      color: #50596c;
      border: 1px solid #e7e9ed;
    }
  `]
            }] }
];
/** @nocollapse */
TableTHeadComponent.ctorParameters = () => [
    { type: StyleService }
];
TableTHeadComponent.propDecorators = {
    config: [{ type: Input }],
    columns: [{ type: Input }],
    sortKey: [{ type: Input }],
    sortState: [{ type: Input }],
    selectAllTemplate: [{ type: Input }],
    filtersTemplate: [{ type: Input }],
    additionalActionsTemplate: [{ type: Input }],
    filter: [{ type: Output }],
    order: [{ type: Output }],
    selectAll: [{ type: Output }],
    event: [{ type: Output }],
    th: [{ type: ViewChild, args: ['th', { static: false },] }],
    additionalActionMenu: [{ type: ViewChild, args: ['additionalActionMenu', { static: false },] }],
    onClick: [{ type: HostListener, args: ['document:click', ['$event.target'],] }]
};
if (false) {
    /** @type {?} */
    TableTHeadComponent.prototype.menuActive;
    /** @type {?} */
    TableTHeadComponent.prototype.openedHeaderActionTemplate;
    /** @type {?} */
    TableTHeadComponent.prototype.startOffset;
    /** @type {?} */
    TableTHeadComponent.prototype.onSelectAllBinded;
    /** @type {?} */
    TableTHeadComponent.prototype.config;
    /** @type {?} */
    TableTHeadComponent.prototype.columns;
    /** @type {?} */
    TableTHeadComponent.prototype.sortKey;
    /** @type {?} */
    TableTHeadComponent.prototype.sortState;
    /** @type {?} */
    TableTHeadComponent.prototype.selectAllTemplate;
    /** @type {?} */
    TableTHeadComponent.prototype.filtersTemplate;
    /** @type {?} */
    TableTHeadComponent.prototype.additionalActionsTemplate;
    /** @type {?} */
    TableTHeadComponent.prototype.filter;
    /** @type {?} */
    TableTHeadComponent.prototype.order;
    /** @type {?} */
    TableTHeadComponent.prototype.selectAll;
    /** @type {?} */
    TableTHeadComponent.prototype.event;
    /**
     * @type {?}
     * @private
     */
    TableTHeadComponent.prototype.th;
    /** @type {?} */
    TableTHeadComponent.prototype.additionalActionMenu;
    /** @type {?} */
    TableTHeadComponent.prototype.styleService;
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class BaseModule {
}
BaseModule.decorators = [
    { type: NgModule, args: [{
                declarations: [
                    BaseComponent,
                    HeaderComponent,
                    PaginationComponent,
                    TableTHeadComponent,
                    // Pipes
                    SearchPipe,
                    RenderPipe,
                    GlobalSearchPipe,
                    SortPipe,
                ],
                imports: [
                    CommonModule,
                    NgxPaginationModule,
                    DragDropModule,
                    ScrollingModule,
                ],
                exports: [BaseComponent],
            },] }
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class TableModule {
}
TableModule.decorators = [
    { type: NgModule, args: [{
                imports: [
                    CommonModule,
                    BaseModule,
                ],
                bootstrap: [BaseComponent],
                exports: [BaseComponent],
                providers: [],
            },] }
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

export { API, DefaultConfig, Event, STYLE, THEME, TableModule, DefaultConfigService as ɵa, BaseModule as ɵb, BaseComponent as ɵc, GroupRowsService as ɵd, StyleService as ɵe, HeaderComponent as ɵf, PaginationComponent as ɵg, TableTHeadComponent as ɵh, SearchPipe as ɵi, RenderPipe as ɵj, GlobalSearchPipe as ɵk, SortPipe as ɵl };
//# sourceMappingURL=ngx-easy-table.js.map