@swimlane/ngx-datatable
Version:
ngx-datatable is an Angular table grid component for presenting large and complex data.
863 lines • 85.5 kB
JavaScript
import { Component, Output, EventEmitter, Input, HostBinding, ViewChild, ChangeDetectionStrategy } from '@angular/core';
import { ScrollerComponent } from './scroller.component';
import { columnsByPin, columnGroupWidths } from '../../utils/column';
import { RowHeightCache } from '../../utils/row-height-cache';
import { translateXY } from '../../utils/translate';
import * as i0 from "@angular/core";
import * as i1 from "./progress-bar.component";
import * as i2 from "./selection.component";
import * as i3 from "./scroller.component";
import * as i4 from "./summary/summary-row.component";
import * as i5 from "./body-row-wrapper.component";
import * as i6 from "./body-row.component";
import * as i7 from "@angular/common";
export class DataTableBodyComponent {
/**
* Creates an instance of DataTableBodyComponent.
*/
constructor(cd) {
this.cd = cd;
this.selected = [];
this.scroll = new EventEmitter();
this.page = new EventEmitter();
this.activate = new EventEmitter();
this.select = new EventEmitter();
this.detailToggle = new EventEmitter();
this.rowContextmenu = new EventEmitter(false);
this.treeAction = new EventEmitter();
this.rowHeightsCache = new RowHeightCache();
this.temp = [];
this.offsetY = 0;
this.indexes = {};
this.rowIndexes = new WeakMap();
this.rowExpansions = [];
/**
* Get the height of the detail row.
*/
this.getDetailRowHeight = (row, index) => {
if (!this.rowDetail) {
return 0;
}
const rowHeight = this.rowDetail.rowHeight;
return typeof rowHeight === 'function' ? rowHeight(row, index) : rowHeight;
};
// declare fn here so we can get access to the `this` property
this.rowTrackingFn = (index, row) => {
const idx = this.getRowIndex(row);
if (this.trackByProp) {
return row[this.trackByProp];
}
else {
return idx;
}
};
}
set pageSize(val) {
this._pageSize = val;
this.recalcLayout();
}
get pageSize() {
return this._pageSize;
}
set rows(val) {
this._rows = val;
this.recalcLayout();
}
get rows() {
return this._rows;
}
set columns(val) {
this._columns = val;
const colsByPin = columnsByPin(val);
this.columnGroupWidths = columnGroupWidths(colsByPin, val);
}
get columns() {
return this._columns;
}
set offset(val) {
this._offset = val;
if (!this.scrollbarV || (this.scrollbarV && !this.virtualization))
this.recalcLayout();
}
get offset() {
return this._offset;
}
set rowCount(val) {
this._rowCount = val;
this.recalcLayout();
}
get rowCount() {
return this._rowCount;
}
get bodyWidth() {
if (this.scrollbarH) {
return this.innerWidth + 'px';
}
else {
return '100%';
}
}
set bodyHeight(val) {
if (this.scrollbarV) {
this._bodyHeight = val + 'px';
}
else {
this._bodyHeight = 'auto';
}
this.recalcLayout();
}
get bodyHeight() {
return this._bodyHeight;
}
/**
* Returns if selection is enabled.
*/
get selectEnabled() {
return !!this.selectionType;
}
/**
* Property that would calculate the height of scroll bar
* based on the row heights cache for virtual scroll and virtualization. Other scenarios
* calculate scroll height automatically (as height will be undefined).
*/
get scrollHeight() {
if (this.scrollbarV && this.virtualization && this.rowCount) {
return this.rowHeightsCache.query(this.rowCount - 1);
}
// avoid TS7030: Not all code paths return a value.
return undefined;
}
/**
* Called after the constructor, initializing input properties
*/
ngOnInit() {
if (this.rowDetail) {
this.listener = this.rowDetail.toggle.subscribe(({ type, value }) => {
if (type === 'row') {
this.toggleRowExpansion(value);
}
if (type === 'all') {
this.toggleAllRows(value);
}
// Refresh rows after toggle
// Fixes #883
this.updateIndexes();
this.updateRows();
this.cd.markForCheck();
});
}
if (this.groupHeader) {
this.listener = this.groupHeader.toggle.subscribe(({ type, value }) => {
if (type === 'group') {
this.toggleRowExpansion(value);
}
if (type === 'all') {
this.toggleAllRows(value);
}
// Refresh rows after toggle
// Fixes #883
this.updateIndexes();
this.updateRows();
this.cd.markForCheck();
});
}
}
/**
* Called once, before the instance is destroyed.
*/
ngOnDestroy() {
if (this.rowDetail || this.groupHeader) {
this.listener.unsubscribe();
}
}
/**
* Updates the Y offset given a new offset.
*/
updateOffsetY(offset) {
// scroller is missing on empty table
if (!this.scroller) {
return;
}
if (this.scrollbarV && this.virtualization && offset) {
// First get the row Index that we need to move to.
const rowIndex = this.pageSize * offset;
offset = this.rowHeightsCache.query(rowIndex - 1);
}
else if (this.scrollbarV && !this.virtualization) {
offset = 0;
}
this.scroller.setOffset(offset || 0);
}
/**
* Body was scrolled, this is mainly useful for
* when a user is server-side pagination via virtual scroll.
*/
onBodyScroll(event) {
const scrollYPos = event.scrollYPos;
const scrollXPos = event.scrollXPos;
// if scroll change, trigger update
// this is mainly used for header cell positions
if (this.offsetY !== scrollYPos || this.offsetX !== scrollXPos) {
this.scroll.emit({
offsetY: scrollYPos,
offsetX: scrollXPos
});
}
this.offsetY = scrollYPos;
this.offsetX = scrollXPos;
this.updateIndexes();
this.updatePage(event.direction);
this.updateRows();
}
/**
* Updates the page given a direction.
*/
updatePage(direction) {
let offset = this.indexes.first / this.pageSize;
if (direction === 'up') {
offset = Math.ceil(offset);
}
else if (direction === 'down') {
offset = Math.floor(offset);
}
if (direction !== undefined && !isNaN(offset)) {
this.page.emit({ offset });
}
}
/**
* Updates the rows in the view port
*/
updateRows() {
const { first, last } = this.indexes;
let rowIndex = first;
let idx = 0;
const temp = [];
// if grouprowsby has been specified treat row paging
// parameters as group paging parameters ie if limit 10 has been
// specified treat it as 10 groups rather than 10 rows
if (this.groupedRows) {
let maxRowsPerGroup = 3;
// if there is only one group set the maximum number of
// rows per group the same as the total number of rows
if (this.groupedRows.length === 1) {
maxRowsPerGroup = this.groupedRows[0].value.length;
}
while (rowIndex < last && rowIndex < this.groupedRows.length) {
// Add the groups into this page
const group = this.groupedRows[rowIndex];
this.rowIndexes.set(group, rowIndex);
if (group.value) {
// add indexes for each group item
group.value.forEach((g, i) => {
const _idx = `${rowIndex}-${i}`;
this.rowIndexes.set(g, _idx);
});
}
temp[idx] = group;
idx++;
// Group index in this context
rowIndex++;
}
}
else {
while (rowIndex < last && rowIndex < this.rowCount) {
const row = this.rows[rowIndex];
if (row) {
// add indexes for each row
this.rowIndexes.set(row, rowIndex);
temp[idx] = row;
}
idx++;
rowIndex++;
}
}
this.temp = temp;
}
/**
* Get the row height
*/
getRowHeight(row) {
// if its a function return it
if (typeof this.rowHeight === 'function') {
return this.rowHeight(row);
}
return this.rowHeight;
}
/**
* @param group the group with all rows
*/
getGroupHeight(group) {
let rowHeight = 0;
if (group.value) {
for (let index = 0; index < group.value.length; index++) {
rowHeight += this.getRowAndDetailHeight(group.value[index]);
}
}
return rowHeight;
}
/**
* Calculate row height based on the expanded state of the row.
*/
getRowAndDetailHeight(row) {
let rowHeight = this.getRowHeight(row);
const expanded = this.getRowExpanded(row);
// Adding detail row height if its expanded.
if (expanded) {
rowHeight += this.getDetailRowHeight(row);
}
return rowHeight;
}
/**
* Calculates the styles for the row so that the rows can be moved in 2D space
* during virtual scroll inside the DOM. In the below case the Y position is
* manipulated. As an example, if the height of row 0 is 30 px and row 1 is
* 100 px then following styles are generated:
*
* transform: translate3d(0px, 0px, 0px); -> row0
* transform: translate3d(0px, 30px, 0px); -> row1
* transform: translate3d(0px, 130px, 0px); -> row2
*
* Row heights have to be calculated based on the row heights cache as we wont
* be able to determine which row is of what height before hand. In the above
* case the positionY of the translate3d for row2 would be the sum of all the
* heights of the rows before it (i.e. row0 and row1).
*
* @param rows the row that needs to be placed in the 2D space.
* @returns the CSS3 style to be applied
*
* @memberOf DataTableBodyComponent
*/
getRowsStyles(rows) {
const styles = {};
// only add styles for the group if there is a group
if (this.groupedRows) {
styles.width = this.columnGroupWidths.total;
}
if (this.scrollbarV && this.virtualization) {
let idx = 0;
if (this.groupedRows) {
// Get the latest row rowindex in a group
const row = rows[rows.length - 1];
idx = row ? this.getRowIndex(row) : 0;
}
else {
idx = this.getRowIndex(rows);
}
// const pos = idx * rowHeight;
// The position of this row would be the sum of all row heights
// until the previous row position.
const pos = this.rowHeightsCache.query(idx - 1);
translateXY(styles, 0, pos);
}
return styles;
}
/**
* Calculate bottom summary row offset for scrollbar mode.
* For more information about cache and offset calculation
* see description for `getRowsStyles` method
*
* @returns the CSS3 style to be applied
*
* @memberOf DataTableBodyComponent
*/
getBottomSummaryRowStyles() {
if (!this.scrollbarV || !this.rows || !this.rows.length) {
return null;
}
const styles = { position: 'absolute' };
const pos = this.rowHeightsCache.query(this.rows.length - 1);
translateXY(styles, 0, pos);
return styles;
}
/**
* Hides the loading indicator
*/
hideIndicator() {
setTimeout(() => (this.loadingIndicator = false), 500);
}
/**
* Updates the index of the rows in the viewport
*/
updateIndexes() {
let first = 0;
let last = 0;
if (this.scrollbarV) {
if (this.virtualization) {
// Calculation of the first and last indexes will be based on where the
// scrollY position would be at. The last index would be the one
// that shows up inside the view port the last.
const height = parseInt(this.bodyHeight, 0);
first = this.rowHeightsCache.getRowIndex(this.offsetY);
last = this.rowHeightsCache.getRowIndex(height + this.offsetY) + 1;
}
else {
// If virtual rows are not needed
// We render all in one go
first = 0;
last = this.rowCount;
}
}
else {
// The server is handling paging and will pass an array that begins with the
// element at a specified offset. first should always be 0 with external paging.
if (!this.externalPaging) {
first = Math.max(this.offset * this.pageSize, 0);
}
last = Math.min(first + this.pageSize, this.rowCount);
}
this.indexes = { first, last };
}
/**
* Refreshes the full Row Height cache. Should be used
* when the entire row array state has changed.
*/
refreshRowHeightCache() {
if (!this.scrollbarV || (this.scrollbarV && !this.virtualization)) {
return;
}
// clear the previous row height cache if already present.
// this is useful during sorts, filters where the state of the
// rows array is changed.
this.rowHeightsCache.clearCache();
// Initialize the tree only if there are rows inside the tree.
if (this.rows && this.rows.length) {
const rowExpansions = new Set();
for (const row of this.rows) {
if (this.getRowExpanded(row)) {
rowExpansions.add(row);
}
}
this.rowHeightsCache.initCache({
rows: this.rows,
rowHeight: this.rowHeight,
detailRowHeight: this.getDetailRowHeight,
externalVirtual: this.scrollbarV && this.externalPaging,
rowCount: this.rowCount,
rowIndexes: this.rowIndexes,
rowExpansions
});
}
}
/**
* Gets the index for the view port
*/
getAdjustedViewPortIndex() {
// Capture the row index of the first row that is visible on the viewport.
// If the scroll bar is just below the row which is highlighted then make that as the
// first index.
const viewPortFirstRowIndex = this.indexes.first;
if (this.scrollbarV && this.virtualization) {
const offsetScroll = this.rowHeightsCache.query(viewPortFirstRowIndex - 1);
return offsetScroll <= this.offsetY ? viewPortFirstRowIndex - 1 : viewPortFirstRowIndex;
}
return viewPortFirstRowIndex;
}
/**
* Toggle the Expansion of the row i.e. if the row is expanded then it will
* collapse and vice versa. Note that the expanded status is stored as
* a part of the row object itself as we have to preserve the expanded row
* status in case of sorting and filtering of the row set.
*/
toggleRowExpansion(row) {
// Capture the row index of the first row that is visible on the viewport.
const viewPortFirstRowIndex = this.getAdjustedViewPortIndex();
const rowExpandedIdx = this.getRowExpandedIdx(row, this.rowExpansions);
const expanded = rowExpandedIdx > -1;
// If the detailRowHeight is auto --> only in case of non-virtualized scroll
if (this.scrollbarV && this.virtualization) {
const detailRowHeight = this.getDetailRowHeight(row) * (expanded ? -1 : 1);
// const idx = this.rowIndexes.get(row) || 0;
const idx = this.getRowIndex(row);
this.rowHeightsCache.update(idx, detailRowHeight);
}
// Update the toggled row and update thive nevere heights in the cache.
if (expanded) {
this.rowExpansions.splice(rowExpandedIdx, 1);
}
else {
this.rowExpansions.push(row);
}
this.detailToggle.emit({
rows: [row],
currentIndex: viewPortFirstRowIndex
});
}
/**
* Expand/Collapse all the rows no matter what their state is.
*/
toggleAllRows(expanded) {
// clear prev expansions
this.rowExpansions = [];
// Capture the row index of the first row that is visible on the viewport.
const viewPortFirstRowIndex = this.getAdjustedViewPortIndex();
if (expanded) {
for (const row of this.rows) {
this.rowExpansions.push(row);
}
}
if (this.scrollbarV) {
// Refresh the full row heights cache since every row was affected.
this.recalcLayout();
}
// Emit all rows that have been expanded.
this.detailToggle.emit({
rows: this.rows,
currentIndex: viewPortFirstRowIndex
});
}
/**
* Recalculates the table
*/
recalcLayout() {
this.refreshRowHeightCache();
this.updateIndexes();
this.updateRows();
}
/**
* Tracks the column
*/
columnTrackingFn(index, column) {
return column.$$id;
}
/**
* Gets the row pinning group styles
*/
stylesByGroup(group) {
const widths = this.columnGroupWidths;
const offsetX = this.offsetX;
const styles = {
width: `${widths[group]}px`
};
if (group === 'left') {
translateXY(styles, offsetX, 0);
}
else if (group === 'right') {
const bodyWidth = parseInt(this.innerWidth + '', 0);
const totalDiff = widths.total - bodyWidth;
const offsetDiff = totalDiff - offsetX;
const offset = offsetDiff * -1;
translateXY(styles, offset, 0);
}
return styles;
}
/**
* Returns if the row was expanded and set default row expansion when row expansion is empty
*/
getRowExpanded(row) {
if (this.rowExpansions.length === 0 && this.groupExpansionDefault) {
for (const group of this.groupedRows) {
this.rowExpansions.push(group);
}
}
return this.getRowExpandedIdx(row, this.rowExpansions) > -1;
}
getRowExpandedIdx(row, expanded) {
if (!expanded || !expanded.length)
return -1;
const rowId = this.rowIdentity(row);
return expanded.findIndex(r => {
const id = this.rowIdentity(r);
return id === rowId;
});
}
/**
* Gets the row index given a row
*/
getRowIndex(row) {
return this.rowIndexes.get(row) || 0;
}
onTreeAction(row) {
this.treeAction.emit({ row });
}
}
DataTableBodyComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DataTableBodyComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
DataTableBodyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.1", type: DataTableBodyComponent, selector: "datatable-body", inputs: { scrollbarV: "scrollbarV", scrollbarH: "scrollbarH", loadingIndicator: "loadingIndicator", externalPaging: "externalPaging", rowHeight: "rowHeight", offsetX: "offsetX", emptyMessage: "emptyMessage", selectionType: "selectionType", selected: "selected", rowIdentity: "rowIdentity", rowDetail: "rowDetail", groupHeader: "groupHeader", selectCheck: "selectCheck", displayCheck: "displayCheck", trackByProp: "trackByProp", rowClass: "rowClass", groupedRows: "groupedRows", groupExpansionDefault: "groupExpansionDefault", innerWidth: "innerWidth", groupRowsBy: "groupRowsBy", virtualization: "virtualization", summaryRow: "summaryRow", summaryPosition: "summaryPosition", summaryHeight: "summaryHeight", pageSize: "pageSize", rows: "rows", columns: "columns", offset: "offset", rowCount: "rowCount", bodyHeight: "bodyHeight" }, outputs: { scroll: "scroll", page: "page", activate: "activate", select: "select", detailToggle: "detailToggle", rowContextmenu: "rowContextmenu", treeAction: "treeAction" }, host: { properties: { "style.width": "this.bodyWidth", "style.height": "this.bodyHeight" }, classAttribute: "datatable-body" }, viewQueries: [{ propertyName: "scroller", first: true, predicate: ScrollerComponent, descendants: true }], ngImport: i0, template: `
<datatable-progress *ngIf="loadingIndicator"> </datatable-progress>
<datatable-selection
#selector
[selected]="selected"
[rows]="rows"
[selectCheck]="selectCheck"
[selectEnabled]="selectEnabled"
[selectionType]="selectionType"
[rowIdentity]="rowIdentity"
(select)="select.emit($event)"
(activate)="activate.emit($event)"
>
<datatable-scroller
*ngIf="rows?.length"
[scrollbarV]="scrollbarV"
[scrollbarH]="scrollbarH"
[scrollHeight]="scrollHeight"
[scrollWidth]="columnGroupWidths?.total"
(scroll)="onBodyScroll($event)"
>
<datatable-summary-row
*ngIf="summaryRow && summaryPosition === 'top'"
[rowHeight]="summaryHeight"
[offsetX]="offsetX"
[innerWidth]="innerWidth"
[rows]="rows"
[columns]="columns"
>
</datatable-summary-row>
<datatable-row-wrapper
[groupedRows]="groupedRows"
*ngFor="let group of temp; let i = index; trackBy: rowTrackingFn"
[innerWidth]="innerWidth"
[ngStyle]="getRowsStyles(group)"
[rowDetail]="rowDetail"
[groupHeader]="groupHeader"
[offsetX]="offsetX"
[detailRowHeight]="getDetailRowHeight(group && group[i], i)"
[row]="group"
[expanded]="getRowExpanded(group)"
[rowIndex]="getRowIndex(group && group[i])"
(rowContextmenu)="rowContextmenu.emit($event)"
>
<datatable-body-row
role="row"
*ngIf="!groupedRows; else groupedRowsTemplate"
tabindex="-1"
[isSelected]="selector.getRowSelected(group)"
[innerWidth]="innerWidth"
[offsetX]="offsetX"
[columns]="columns"
[rowHeight]="getRowHeight(group)"
[row]="group"
[rowIndex]="getRowIndex(group)"
[expanded]="getRowExpanded(group)"
[rowClass]="rowClass"
[displayCheck]="displayCheck"
[treeStatus]="group && group.treeStatus"
(treeAction)="onTreeAction(group)"
(activate)="selector.onActivate($event, indexes.first + i)"
>
</datatable-body-row>
<ng-template #groupedRowsTemplate>
<datatable-body-row
role="row"
*ngFor="let row of group.value; let i = index; trackBy: rowTrackingFn"
tabindex="-1"
[isSelected]="selector.getRowSelected(row)"
[innerWidth]="innerWidth"
[offsetX]="offsetX"
[columns]="columns"
[rowHeight]="getRowHeight(row)"
[row]="row"
[group]="group.value"
[rowIndex]="getRowIndex(row)"
[expanded]="getRowExpanded(row)"
[rowClass]="rowClass"
(activate)="selector.onActivate($event, i)"
>
</datatable-body-row>
</ng-template>
</datatable-row-wrapper>
<datatable-summary-row
role="row"
*ngIf="summaryRow && summaryPosition === 'bottom'"
[ngStyle]="getBottomSummaryRowStyles()"
[rowHeight]="summaryHeight"
[offsetX]="offsetX"
[innerWidth]="innerWidth"
[rows]="rows"
[columns]="columns"
>
</datatable-summary-row>
</datatable-scroller>
<div class="empty-row" *ngIf="!rows?.length && !loadingIndicator" [innerHTML]="emptyMessage"></div>
</datatable-selection>
`, isInline: true, components: [{ type: i1.ProgressBarComponent, selector: "datatable-progress" }, { type: i2.DataTableSelectionComponent, selector: "datatable-selection", inputs: ["rows", "selected", "selectEnabled", "selectionType", "rowIdentity", "selectCheck"], outputs: ["activate", "select"] }, { type: i3.ScrollerComponent, selector: "datatable-scroller", inputs: ["scrollbarV", "scrollbarH", "scrollHeight", "scrollWidth"], outputs: ["scroll"] }, { type: i4.DataTableSummaryRowComponent, selector: "datatable-summary-row", inputs: ["rows", "columns", "rowHeight", "offsetX", "innerWidth"] }, { type: i5.DataTableRowWrapperComponent, selector: "datatable-row-wrapper", inputs: ["innerWidth", "rowDetail", "groupHeader", "offsetX", "detailRowHeight", "row", "groupedRows", "rowIndex", "expanded"], outputs: ["rowContextmenu"] }, { type: i6.DataTableBodyRowComponent, selector: "datatable-body-row", inputs: ["columns", "innerWidth", "expanded", "rowClass", "row", "group", "isSelected", "rowIndex", "displayCheck", "treeStatus", "offsetX", "rowHeight"], outputs: ["activate", "treeAction"] }], directives: [{ type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DataTableBodyComponent, decorators: [{
type: Component,
args: [{
selector: 'datatable-body',
template: `
<datatable-progress *ngIf="loadingIndicator"> </datatable-progress>
<datatable-selection
#selector
[selected]="selected"
[rows]="rows"
[selectCheck]="selectCheck"
[selectEnabled]="selectEnabled"
[selectionType]="selectionType"
[rowIdentity]="rowIdentity"
(select)="select.emit($event)"
(activate)="activate.emit($event)"
>
<datatable-scroller
*ngIf="rows?.length"
[scrollbarV]="scrollbarV"
[scrollbarH]="scrollbarH"
[scrollHeight]="scrollHeight"
[scrollWidth]="columnGroupWidths?.total"
(scroll)="onBodyScroll($event)"
>
<datatable-summary-row
*ngIf="summaryRow && summaryPosition === 'top'"
[rowHeight]="summaryHeight"
[offsetX]="offsetX"
[innerWidth]="innerWidth"
[rows]="rows"
[columns]="columns"
>
</datatable-summary-row>
<datatable-row-wrapper
[groupedRows]="groupedRows"
*ngFor="let group of temp; let i = index; trackBy: rowTrackingFn"
[innerWidth]="innerWidth"
[ngStyle]="getRowsStyles(group)"
[rowDetail]="rowDetail"
[groupHeader]="groupHeader"
[offsetX]="offsetX"
[detailRowHeight]="getDetailRowHeight(group && group[i], i)"
[row]="group"
[expanded]="getRowExpanded(group)"
[rowIndex]="getRowIndex(group && group[i])"
(rowContextmenu)="rowContextmenu.emit($event)"
>
<datatable-body-row
role="row"
*ngIf="!groupedRows; else groupedRowsTemplate"
tabindex="-1"
[isSelected]="selector.getRowSelected(group)"
[innerWidth]="innerWidth"
[offsetX]="offsetX"
[columns]="columns"
[rowHeight]="getRowHeight(group)"
[row]="group"
[rowIndex]="getRowIndex(group)"
[expanded]="getRowExpanded(group)"
[rowClass]="rowClass"
[displayCheck]="displayCheck"
[treeStatus]="group && group.treeStatus"
(treeAction)="onTreeAction(group)"
(activate)="selector.onActivate($event, indexes.first + i)"
>
</datatable-body-row>
<ng-template #groupedRowsTemplate>
<datatable-body-row
role="row"
*ngFor="let row of group.value; let i = index; trackBy: rowTrackingFn"
tabindex="-1"
[isSelected]="selector.getRowSelected(row)"
[innerWidth]="innerWidth"
[offsetX]="offsetX"
[columns]="columns"
[rowHeight]="getRowHeight(row)"
[row]="row"
[group]="group.value"
[rowIndex]="getRowIndex(row)"
[expanded]="getRowExpanded(row)"
[rowClass]="rowClass"
(activate)="selector.onActivate($event, i)"
>
</datatable-body-row>
</ng-template>
</datatable-row-wrapper>
<datatable-summary-row
role="row"
*ngIf="summaryRow && summaryPosition === 'bottom'"
[ngStyle]="getBottomSummaryRowStyles()"
[rowHeight]="summaryHeight"
[offsetX]="offsetX"
[innerWidth]="innerWidth"
[rows]="rows"
[columns]="columns"
>
</datatable-summary-row>
</datatable-scroller>
<div class="empty-row" *ngIf="!rows?.length && !loadingIndicator" [innerHTML]="emptyMessage"></div>
</datatable-selection>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
class: 'datatable-body'
}
}]
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { scrollbarV: [{
type: Input
}], scrollbarH: [{
type: Input
}], loadingIndicator: [{
type: Input
}], externalPaging: [{
type: Input
}], rowHeight: [{
type: Input
}], offsetX: [{
type: Input
}], emptyMessage: [{
type: Input
}], selectionType: [{
type: Input
}], selected: [{
type: Input
}], rowIdentity: [{
type: Input
}], rowDetail: [{
type: Input
}], groupHeader: [{
type: Input
}], selectCheck: [{
type: Input
}], displayCheck: [{
type: Input
}], trackByProp: [{
type: Input
}], rowClass: [{
type: Input
}], groupedRows: [{
type: Input
}], groupExpansionDefault: [{
type: Input
}], innerWidth: [{
type: Input
}], groupRowsBy: [{
type: Input
}], virtualization: [{
type: Input
}], summaryRow: [{
type: Input
}], summaryPosition: [{
type: Input
}], summaryHeight: [{
type: Input
}], pageSize: [{
type: Input
}], rows: [{
type: Input
}], columns: [{
type: Input
}], offset: [{
type: Input
}], rowCount: [{
type: Input
}], bodyWidth: [{
type: HostBinding,
args: ['style.width']
}], bodyHeight: [{
type: Input
}, {
type: HostBinding,
args: ['style.height']
}], scroll: [{
type: Output
}], page: [{
type: Output
}], activate: [{
type: Output
}], select: [{
type: Output
}], detailToggle: [{
type: Output
}], rowContextmenu: [{
type: Output
}], treeAction: [{
type: Output
}], scroller: [{
type: ViewChild,
args: [ScrollerComponent]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9keS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zd2ltbGFuZS9uZ3gtZGF0YXRhYmxlL3NyYy9saWIvY29tcG9uZW50cy9ib2R5L2JvZHkuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsTUFBTSxFQUNOLFlBQVksRUFDWixLQUFLLEVBQ0wsV0FBVyxFQUVYLFNBQVMsRUFHVCx1QkFBdUIsRUFDeEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFekQsT0FBTyxFQUFFLFlBQVksRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7Ozs7Ozs7OztBQTJHcEQsTUFBTSxPQUFPLHNCQUFzQjtJQWlKakM7O09BRUc7SUFDSCxZQUFvQixFQUFxQjtRQUFyQixPQUFFLEdBQUYsRUFBRSxDQUFtQjtRQTNJaEMsYUFBUSxHQUFVLEVBQUUsQ0FBQztRQXdGcEIsV0FBTSxHQUFzQixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQy9DLFNBQUksR0FBc0IsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUM3QyxhQUFRLEdBQXNCLElBQUksWUFBWSxFQUFFLENBQUM7UUFDakQsV0FBTSxHQUFzQixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQy9DLGlCQUFZLEdBQXNCLElBQUksWUFBWSxFQUFFLENBQUM7UUFDckQsbUJBQWMsR0FBRyxJQUFJLFlBQVksQ0FBa0MsS0FBSyxDQUFDLENBQUM7UUFDMUUsZUFBVSxHQUFzQixJQUFJLFlBQVksRUFBRSxDQUFDO1FBd0I3RCxvQkFBZSxHQUFtQixJQUFJLGNBQWMsRUFBRSxD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