ngx-ui-hero
Version:
Simple, fast and reliable utilities for Angular.
856 lines • 178 kB
JavaScript
import { clone, filter, find, map, orderBy, some, sum, sumBy } from "lodash-es";
import { BsModalService } from "ngx-bootstrap/modal";
import { PaginationComponent, } from "ngx-bootstrap/pagination";
import { Component, ContentChild, EventEmitter, Inject, Input, IterableDiffers, Optional, Output, Renderer2, TemplateRef, ViewChild, } from "@angular/core";
import { DomSanitizer } from "@angular/platform-browser";
import { EnumAutoFitMode, EnumDataGridMode, } from "./config/data-grid-config";
import { DATAGRID_CONFIG } from "./config/data-grid-config.constants";
import { DatagridExportingModalComponent } from "./datagrid-exporting-modal/datagrid-exporting-modal.component";
import { ActionsColumnDirective } from "./directives/data-grid-templates.directive";
import { DataGridSortingModel, EnumAlignment, EnumSortDirection, } from "./models/data-grid-column.model";
import * as i0 from "@angular/core";
import * as i1 from "ngx-bootstrap/modal";
import * as i2 from "@angular/platform-browser";
import * as i3 from "@angular/common";
import * as i4 from "@angular/forms";
import * as i5 from "../ui/components/spinner/spinner.component";
import * as i6 from "ngx-bootstrap/pagination";
import * as i7 from "ngx-bootstrap/dropdown";
import * as i8 from "ngx-bootstrap/popover";
import * as i9 from "./components/column-filter/column-filter.component";
let identifier = 0;
export class GridDataModel {
}
export class GridRowModel {
}
export class GridColumnModel {
}
export class DataGridComponent {
constructor(defaultOptions, iterableDiffers, modalService, renderer, sanitizer) {
this.iterableDiffers = iterableDiffers;
this.modalService = modalService;
this.renderer = renderer;
this.sanitizer = sanitizer;
this.initialRenderApplied = false;
this.sortApplied = false;
this.animating = false;
this.selectAll = false;
this.isResizing = false;
this.isReordering = false;
this.currentElementBeingReorderedFromIndex = -1;
this.currentElementBeingReorderedToIndex = -1;
this.currentPage = 1;
this.identifier = `datagrid-${identifier++}`;
this.debugMode = false;
this.tableId = this.identifier;
this.emptyResultsMessage = "No results found at this moment.";
this.infoMessage = "Showing records from {recordsFrom} to {recordsTo} of {totalRecords} records found.";
this.animated = true;
this.striped = true;
this.bordered = true;
this.hoverEffect = true;
this.responsive = true;
this.showCheckboxColumn = false;
this.showSelectAllCheckbox = true;
this.selectAllPages = true;
this.checkBoxMode = 0;
this.showSummaries = false;
this.allowExports = false;
this.exportButtonLabel = "Export";
this.exportedFileName = "Export";
this.exportedExcelSheetName = "Sheet";
this.initialColumnToSort = 0;
this.initialSortDirection = EnumSortDirection.Ascending;
this.mode = EnumDataGridMode.OnClient;
this.itemsPerPage = 10;
this.maxSize = 10;
this.boundaryLinks = true;
this.directionLinks = true;
this.rotate = true;
this.showActionsColumn = false;
this.showInfos = true;
this.actionsColumnCaption = "#";
this.actionsColumnWidth = "100px";
this.firstText = "First";
this.previousText = "Previous";
this.nextText = "Next";
this.lastText = "Last";
this.autoFitMode = EnumAutoFitMode.ByContent;
this.allowColumnResize = true;
this.allowColumnFilters = true;
this.allowColumnReorder = true;
this.fixedHeader = false;
this.minHeight = 200;
this.filterPlaceholder = "Filter...";
this.filterPlacement = "bottom";
this.OnSelectionChanged = new EventEmitter();
this.OnRowSelected = new EventEmitter();
this.OnRowRendered = new EventEmitter();
this.OnPaginate = new EventEmitter();
this.OnSort = new EventEmitter();
this.OnColumnFiltered = new EventEmitter();
this._maxWidth = 400;
this._minColumnWidth = 150;
Object.assign(this, defaultOptions);
if (defaultOptions.paging) {
Object.assign(this, defaultOptions.paging);
}
if (defaultOptions.styles) {
Object.assign(this, defaultOptions.styles);
}
if (defaultOptions.exporting) {
Object.assign(this, defaultOptions.exporting);
}
if (defaultOptions.filtering) {
Object.assign(this, defaultOptions.filtering);
}
if (defaultOptions.reordering) {
Object.assign(this, defaultOptions.reordering);
}
this._dataDiffer = this.iterableDiffers.find([]).create(null);
}
get data() {
return this._externalData;
}
set data(value) {
this._externalData = value;
if (this.isUndefinedOrNull(value) &&
!this.isUndefinedOrNull(this._internalData)) {
this.initializeRendering(true);
}
}
ngOnInit() {
this.draw();
}
ngDoCheck() {
let dataHasChanges = this._dataDiffer.diff(this._externalData);
if (dataHasChanges && this.initialRenderApplied) {
this.initializeRendering(true);
}
}
ToogleSorting(column) {
if (!column.sortable || !column.sort || this.isResizing) {
return;
}
if (this.mode == EnumDataGridMode.OnClient) {
if (column.sort.sorting) {
if (column.sort.sortDirection == EnumSortDirection.Ascending) {
column.sort.sortDirection = EnumSortDirection.Descending;
}
else {
column.sort.sortDirection = EnumSortDirection.Ascending;
}
}
else {
for (let i = 0; i < this.columns.length; i++) {
this.columns[i].sort.sorting = false;
}
column.sort.sorting = true;
column.sort.sortDirection = EnumSortDirection.Ascending;
}
this.sortOnClient(column);
this.paginateOnClient(this.currentPage);
}
else {
if (this.isUndefinedOrNull(this.OnSort)) {
console.error("The [OnSort] callback must be provided when DataGrid Server mode is enabled.");
return;
}
this.OnSort.emit(column);
}
}
PageChanged(event) {
if (this.mode == EnumDataGridMode.OnClient) {
this.paginateOnClient(event.page);
}
else {
if (this.isUndefinedOrNull(this.OnPaginate)) {
console.error("The [OnPaginate] callback must be provided when DataGrid Server mode is enabled.");
return;
}
}
this.OnPaginate.emit(event);
}
GetInfo() {
let result = this.infoMessage;
let recordsFrom = this.currentPage * this.itemsPerPage - (this.itemsPerPage - 1);
let recordsTo = this.currentPage * this.itemsPerPage;
let totalRecords = this.totalItems;
if (recordsTo > totalRecords) {
recordsTo = recordsTo - (recordsTo - totalRecords);
}
return result
.replace("{recordsFrom}", recordsFrom.toString())
.replace("{recordsTo}", recordsTo.toString())
.replace("{totalRecords}", totalRecords.toString());
}
Redraw() {
this.draw();
}
RenderPropertyValue(propertyPath, object) {
if (!propertyPath)
return null;
let parts = propertyPath.split(".");
let property = object || {};
for (let i = 0; i < parts.length; i++) {
if (!property) {
return null;
}
property = property[parts[i]];
}
return property;
}
RenderColumnSummary(column) {
if (!this.gridData || !this.gridData.hasData) {
return 0;
}
return sumBy(this.gridData.rows, (x) => Number(this.RenderPropertyValue(column.data, x.model)));
}
HasSummarizableColumns() {
if (!this.columns || this.columns.length == 0) {
return false;
}
return some(this.columns, (x) => x.summarizable);
}
OnSelectAllChanged() {
if (!this.gridData || !this.gridData.hasData) {
return;
}
for (let i = 0; i < this.gridData.rows.length; i++) {
this.gridData.rows[i].selected = this.selectAll;
if (!this.selectAllPages) {
switch (this.mode) {
case EnumDataGridMode.OnServer:
this._internalData[i].selected = this.selectAll;
break;
default:
this._internalData[i + this.itemsPerPage * (this.currentPage - 1)].selected = this.selectAll;
break;
}
}
}
if (this.selectAllPages) {
for (let i = 0; i < this._internalData.length; i++) {
this._internalData[i].selected = this.selectAll;
}
}
this.OnSelectionChanged.emit();
}
OnRowSelectedChanged(row, rowIndex) {
switch (this.mode) {
case EnumDataGridMode.OnServer:
this._internalData[rowIndex].selected = row.selected;
break;
default:
this._internalData[rowIndex + this.itemsPerPage * (this.currentPage - 1)].selected = row.selected;
break;
}
this.handleSelectAllCheckboxState();
this.OnRowSelected.emit(row);
this.OnSelectionChanged.emit();
}
async ExportToExcel(event) {
event.preventDefault();
let _data = this.boundedExportCallback
? await this.boundedExportCallback()
: this._externalData;
this.modalService.show(DatagridExportingModalComponent, {
class: "modal-md",
initialState: {
data: _data,
columns: this.columns.slice(0),
exportedFileName: this.exportedFileName,
exportedExcelSheetName: this.exportedExcelSheetName,
initialColumnToSort: this.initialColumnToSort,
initialSortDirection: this.initialSortDirection,
},
});
return false;
}
OnResizerMouseDown(e) {
if (!this.allowColumnResize)
return;
this.isResizing = true;
var pageX, curCol, nxtCol, curColWidth, nxtColWidth;
curCol = e.target.parentElement;
nxtCol = curCol.nextElementSibling;
pageX = e.pageX;
var padding = this.paddingDiff(curCol);
curColWidth = curCol.offsetWidth - padding;
if (nxtCol)
nxtColWidth = nxtCol.offsetWidth - padding;
var onMouseMoveCallback = (e) => {
if (curCol) {
var diffX = e.pageX - pageX;
if (nxtCol)
nxtCol.style.width = nxtColWidth - diffX + "px";
curCol.style.width = curColWidth + diffX + "px";
}
};
var onMouseUpCallback = (e) => {
curCol = undefined;
nxtCol = undefined;
pageX = undefined;
nxtColWidth = undefined;
curColWidth = undefined;
setTimeout(() => {
this.isResizing = false;
});
document.removeEventListener("mousemove", onMouseMoveCallback);
document.removeEventListener("mouseup", onMouseUpCallback);
};
document.addEventListener("mousemove", onMouseMoveCallback);
document.addEventListener("mouseup", onMouseUpCallback);
}
OnColumnMouseDown(e, index) {
if (!this.allowColumnReorder)
return;
var onDragStartCallback = (e) => {
var img = document.createElement("img");
e.dataTransfer.setDragImage(img, 0, 0);
this.isReordering = true;
this.currentElementBeingReorderedFromIndex = index;
this.renderer.addClass(e.target.parentElement.parentElement, "dragging");
e.target.addEventListener("dragenter", (e) => onDragEnterCallback(e, index));
e.target.addEventListener("dragend", onDragEndCallback);
$(`#${this.identifier} thead tr th.column`).each((i, el) => {
if (i != index) {
el.addEventListener("dragenter", (e) => onDragEnterCallback(e, i));
el.addEventListener("dragover", onDragOverCallback);
}
});
};
var onDragEndCallback = (e) => {
if (this.currentElementBeingReorderedFromIndex !=
this.currentElementBeingReorderedToIndex) {
this.debug("From", this.currentElementBeingReorderedFromIndex, "To", this.currentElementBeingReorderedToIndex);
var columnFromCopy = Object.assign({}, this.columns[this.currentElementBeingReorderedFromIndex]);
var columnsCopy = Object.assign([], this.columns);
columnsCopy.splice(this.currentElementBeingReorderedFromIndex, 1);
columnsCopy.splice(this.currentElementBeingReorderedToIndex, 0, columnFromCopy);
this.columns = columnsCopy;
this.updateColumnReorderingDefinition();
}
this.isReordering = false;
this.currentElementBeingReorderedFromIndex = -1;
this.currentElementBeingReorderedToIndex = -1;
this.renderer.removeClass(e.target.parentElement.parentElement, "dragging");
e.target.removeEventListener("dragenter", (e) => onDragEnterCallback(e, index));
e.target.removeEventListener("dragend", onDragEndCallback);
$(`#${this.identifier} thead tr th.column`).each((i, el) => {
if (i != index) {
el.removeEventListener("dragenter", (e) => onDragEnterCallback(e, i));
el.removeEventListener("dragover", onDragOverCallback);
}
});
this.initializeRendering();
};
var onDragEnterCallback = (e, i) => {
this.currentElementBeingReorderedToIndex = i;
};
var onDragOverCallback = (e) => {
e.preventDefault();
};
var onMouseUpCallback = (e) => {
e.target.removeEventListener("dragstart", onDragStartCallback);
e.target.removeEventListener("mouseup", onMouseUpCallback);
};
e.target.addEventListener("dragstart", onDragStartCallback);
e.target.addEventListener("mouseup", onMouseUpCallback);
}
OnColumnFilterClick(e, column) {
if (!column.isFiltersOpenned) {
this.closeAllColumnsFilters();
column.isFiltersOpenned = true;
}
else {
this.closeAllColumnsFilters();
}
e.stopPropagation();
}
OnFiltersChange(column) {
if (this.mode == EnumDataGridMode.OnServer) {
this.OnColumnFiltered.emit(column);
}
else {
this.initializeRendering();
}
}
HandleColumnClick(row, currentData, rowIndex, column) {
if (!column.onClick)
return;
column.onClick(row, currentData, rowIndex, column);
}
HandleColumnRendering(row, currentData, rowIndex, column) {
if (!column.render)
return "";
return this.sanitizer.bypassSecurityTrustHtml(column.render(row, currentData, rowIndex));
}
draw(redrawing) {
this.initializeColumns();
this.initializeRendering(redrawing);
}
initializeRendering(redrawing) {
setTimeout(() => {
this.initializeGridData();
this.initializeFilters();
this.initializePaging(redrawing);
this.initializeSorting();
this.handleAutoFit();
this.handleInitialRenderingFlag();
}, 0);
}
initializeGridData() {
if (this._externalData) {
this._internalData = Object.assign([], this._externalData);
}
else {
this._internalData = [];
}
if (this.mode == EnumDataGridMode.OnServer) {
this.initGridDataModel(Object.assign([], this._internalData));
this.handleRowRenders();
}
}
initGridDataModel(data) {
this.gridData = {
hasData: data && data.length > 0,
rows: map(data, (row, rowIndex) => {
let _row = {
selected: row.selected,
model: row,
columns: map(this.columns, (column, columnIndex) => {
let _column = {
isHtml: column.render != undefined,
};
if (column.data) {
if (column.data.split(".").length > 1) {
_column.value = this.RenderPropertyValue(column.data, row);
}
else {
_column.value = row[column.data];
}
}
if (_column.isHtml) {
_column.value = this.HandleColumnRendering(row, _column.value, rowIndex, column);
}
return _column;
}),
};
return _row;
}),
};
}
initializeColumns() {
if (!this.columns || this.columns.length == 0) {
console.error("Param [columns] cannot be undefined or empty.");
return;
}
if (!this._externalColumns)
this._externalColumns = clone(this.columns);
for (let i = 0; i < this.columns.length; i++) {
let target = {
caption: null,
captionAlignment: EnumAlignment.Left,
captionClasses: null,
data: null,
dataAlignment: EnumAlignment.Left,
dataClasses: null,
sortable: true,
filterable: true,
visible: true,
index: i,
};
Object.assign(target, this.columns[i]);
this.columns[i] = target;
this.columns[i].sort = new DataGridSortingModel();
if (!this.isUndefinedOrNull(this.initialColumnToSort) &&
this.initialColumnToSort == i) {
this.columns[i].sort.sorting = true;
if (this.columns[i].sortDirection) {
this.columns[i].sort.sortDirection = this.columns[i].sortDirection;
}
else {
this.columns[i].sort.sortDirection = this.initialSortDirection;
}
}
}
if (!this._internalColumns)
this._internalColumns = clone(this.columns);
this.filterColumnsThatShouldBeVisible();
this.verifyColumnIndexPersistences();
}
initializeSorting() {
if (this.isUndefinedOrNull(this._internalData) ||
this.mode == EnumDataGridMode.OnServer ||
this.isUndefinedOrNull(this.initialColumnToSort)) {
this.sortApplied = true;
return;
}
if (this.initialColumnToSort > this.columns.length - 1) {
console.error("Param [initialColumnToSort] greater than the number of columns.");
this.sortApplied = true;
return;
}
const columnToSort = find(this.columns, (x) => x.sortable && x.sort && x.sort.sorting);
if (this.isUndefinedOrNull(columnToSort)) {
this.paginateOnClient(this.currentPage);
}
else {
this.sortOnClient(columnToSort);
this.paginateOnClient(this.currentPage);
}
this.sortApplied = true;
}
initializePaging(redrawing) {
if (!this.currentPage) {
this.currentPage = 1;
}
if (this._internalData && this.mode == EnumDataGridMode.OnClient) {
this.totalItems = this._internalData.length;
}
let currentPageFitsTheNumberOfItems = this.totalItems > this.itemsPerPage * (this.currentPage - 1);
let shouldResetCurrentPage = this.currentPage > 1 &&
this.mode == EnumDataGridMode.OnClient &&
!currentPageFitsTheNumberOfItems;
if ((redrawing && this.mode == EnumDataGridMode.OnClient) ||
shouldResetCurrentPage) {
this.currentPage = 1;
}
if (this.paginator) {
this.paginator.page = this.currentPage;
this.paginator.totalItems = this.totalItems;
}
}
paddingDiff(col) {
if (this.getStyleVal(col, "box-sizing") == "border-box") {
return 0;
}
var padLeft = this.getStyleVal(col, "padding-left");
var padRight = this.getStyleVal(col, "padding-right");
return parseInt(padLeft) + parseInt(padRight);
}
getStyleVal(elm, css) {
return window.getComputedStyle(elm, null).getPropertyValue(css);
}
isUndefinedOrNull(value) {
return value == undefined || value == null;
}
sortOnClient(column) {
this._internalData = orderBy(this._internalData, [column.data], [column.sort.sortDirection]);
}
paginateOnClient(page) {
const startItem = (page - 1) * this.itemsPerPage;
const endItem = page * this.itemsPerPage;
this.initGridDataModel(this._internalData.slice(startItem, endItem));
this.handleRowRenders();
this.handleSelectAllCheckboxState();
this.handleAutoFit();
}
handleAutoFit() {
switch (this.autoFitMode) {
case EnumAutoFitMode.ByContent:
this.autofitByContent();
break;
case EnumAutoFitMode.ByCaption:
this.autofitByCaption();
break;
default:
this.autofitByFixedWidths();
break;
}
}
autofitByContent() {
if (!this.gridData || !this.gridData.hasData) {
this.autofitByCaption();
return;
}
this.animating = true;
setTimeout(() => {
let widths = [];
let gridWidth = $(`#${this.tableId}`).parent().width();
if (gridWidth == 0 &&
$(`#${this.tableId}`).parents(".tab-content").length) {
gridWidth = $(`#${this.tableId}`).parents(".tab-content").width();
}
for (let rowIndex = 0; rowIndex < this.gridData.rows.length; rowIndex++) {
for (let columnIndex = 0; columnIndex < this.columns.length; columnIndex++) {
let width = this._minColumnWidth;
let currentData = null;
if (!this.gridData.rows[rowIndex].columns[columnIndex].isHtml) {
currentData =
this.gridData.rows[rowIndex].columns[columnIndex].value;
}
if (!this.isUndefinedOrNull(currentData)) {
width = currentData.toString().length * 10 + 20;
}
if (!this.isUndefinedOrNull(this.columns[columnIndex].caption)) {
let widthByCaption = this.columns[columnIndex].caption.toString().length * 10 + 40;
if (widthByCaption > width) {
width = widthByCaption;
if (this.allowColumnResize) {
width += 20;
}
if ((this.allowColumnFilters &&
this.columns[columnIndex].filterable &&
this.isUndefinedOrNull(widths[columnIndex])) ||
width > widths[columnIndex]) {
width += 30;
}
}
}
if (this.isUndefinedOrNull(widths[columnIndex]) ||
width > widths[columnIndex]) {
if (width > this._maxWidth) {
widths[columnIndex] = this._maxWidth;
}
else {
widths[columnIndex] = width;
}
}
}
}
this.setDataGridWidths(widths, gridWidth);
this.animating = false;
}, 0);
}
autofitByCaption() {
this.animating = true;
setTimeout(() => {
for (let columnIndex = 0; columnIndex < this.columns.length; columnIndex++) {
if (this.isUndefinedOrNull(this.columns[columnIndex].width)) {
let widthByCaption = this.columns[columnIndex].caption.toString().length * 10 + 40;
if (this.allowColumnResize) {
widthByCaption += 10;
}
if (this.allowColumnFilters && this.columns[columnIndex].filterable) {
widthByCaption += 30;
}
this.columns[columnIndex].width = `${widthByCaption}px`;
}
}
this.animating = false;
}, 0);
}
autofitByFixedWidths() {
this.animating = true;
setTimeout(() => {
for (let columnIndex = 0; columnIndex < this.columns.length; columnIndex++) {
if (this.isUndefinedOrNull(this.columns[columnIndex].width)) {
this.columns[columnIndex].width = "150px";
}
}
this.animating = false;
}, 0);
}
handleSelectAllCheckboxState() {
if (!this.gridData || !this.gridData.hasData) {
this.selectAll = false;
return;
}
this.selectAll =
this.gridData.rows.filter((x) => x.selected).length ==
this.gridData.rows.length;
}
setDataGridWidths(widths, gridWidth) {
let initialColumnsWidths = new Array(this.columns.length);
let _externalColumns = this._externalColumns.filter((x) => x.visible == undefined || x.visible == true);
for (let i = 0; i < _externalColumns.length; i++) {
let columnDefaultWidth = _externalColumns[i].width;
let def = this.getColumnReorderingDefinitionFrom(_externalColumns[i]);
if (!def) {
initialColumnsWidths[i] = columnDefaultWidth;
continue;
}
initialColumnsWidths[def.userIndex] = columnDefaultWidth;
}
this.debug("initialColumnsWidths", initialColumnsWidths);
let totalColumnsWidth = sum(widths);
let totalColumnsWidthGreaterThanGrid = totalColumnsWidth > gridWidth;
if (!totalColumnsWidthGreaterThanGrid) {
let biggestColumnIndex = 0;
let biggestWidth = widths[widths.length - 1];
for (let i = widths.length - 2; i >= 0; i--) {
if (widths[i] > biggestWidth) {
biggestWidth = widths[i];
biggestColumnIndex = i;
}
}
for (let columnIndex = 0; columnIndex < this.columns.length; columnIndex++) {
if (columnIndex == biggestColumnIndex) {
this.columns[columnIndex].width = `auto`;
if (widths[columnIndex] >= this._maxWidth) {
if (!this.columns[columnIndex].dataClasses) {
this.columns[columnIndex].dataClasses = "";
}
this.columns[columnIndex].dataClasses += " td-break-word";
}
}
else {
this.columns[columnIndex].width = `${widths[columnIndex]}px`;
}
}
}
else {
for (let columnIndex = 0; columnIndex < this.columns.length; columnIndex++) {
if (widths[columnIndex] >= this._maxWidth) {
if (!this.columns[columnIndex].dataClasses) {
this.columns[columnIndex].dataClasses = "";
}
this.columns[columnIndex].dataClasses += " td-break-word";
}
this.columns[columnIndex].width = `${widths[columnIndex]}px`;
}
}
for (let i = 0; i < initialColumnsWidths.length; i++) {
if (initialColumnsWidths[i]) {
this.columns[i].width = initialColumnsWidths[i];
}
}
}
handleInitialRenderingFlag() {
if (!this.initialRenderApplied) {
this.initialRenderApplied = true;
}
}
initializeFilters() {
if (!this.columns ||
this.columns.length == 0 ||
!this.data ||
this.data.length == 0 ||
this.mode == EnumDataGridMode.OnServer)
return;
let filters = [];
for (let i = 0; i < this.columns.length; i++) {
if (this.columns[i].simpleFilter) {
filters.push(this.columns[i].simpleFilter);
}
if (this.columns[i].customFilters &&
this.columns[i].customFilters.length > 0) {
filters.push(...this.columns[i].customFilters);
}
}
if (!filters || filters.length == 0)
return;
this._internalData = this.data.filter((row, rowIndex) => {
for (let i = 0; i < filters.length; i++) {
let value = null;
if (filters[i].column.render)
value = filters[i].column.render(row, this.RenderPropertyValue(filters[i].column.data, row), rowIndex);
else
value = this.RenderPropertyValue(filters[i].column.data, row);
if (!filters[i].operator.validate(filters[i].filter, value)) {
return false;
}
}
return true;
});
}
closeAllColumnsFilters() {
if (!this.columns || this.columns.length == 0)
return;
for (let i = 0; i < this.columns.length; i++) {
this.columns[i].isFiltersOpenned = false;
}
}
handleRowRenders() {
if (!this.gridData || !this.gridData.hasData)
return;
for (let i = 0; i < this.gridData.rows.length; i++) {
this.OnRowRendered.emit(this.gridData.rows[i]);
}
}
verifyColumnIndexPersistences() {
if (!this.userPreferencesKey)
return;
let definition = this.getOrCreateColumnReorderingDefinition();
this.applyColumnReorderingDefinition(definition);
}
getColumnReorderingDefinition() {
if (this._columnDefinitions)
return this._columnDefinitions;
this.debug("Readed from localstorage");
let json = localStorage.getItem(this.userPreferencesKey);
this._columnDefinitions = json ? JSON.parse(json) : null;
return this._columnDefinitions;
}
getOrCreateColumnReorderingDefinition() {
let definition = this.getColumnReorderingDefinition();
if (!definition || this.definitionIsNotCompatibleAnymore(definition)) {
return this.buildColumnReorderingDefinition();
}
return definition;
}
buildColumnReorderingDefinition() {
let definition = {
key: this.userPreferencesKey,
data: this.columns.map((c) => {
let item = {
caption: c.caption,
originalIndex: c.index,
userIndex: c.index,
};
return item;
}),
};
this._columnDefinitions = definition;
localStorage.setItem(this.userPreferencesKey, JSON.stringify(definition));
this.debug("Rebuilded ColumnReorderingDefinition");
return definition;
}
definitionIsNotCompatibleAnymore(definition) {
this.debug("Compatibility checking on:", definition);
let hasDifferentNumberOfColumns = this.columns.length != definition.data.length;
this.debug("hasDifferentNumberOfColumns", hasDifferentNumberOfColumns);
if (hasDifferentNumberOfColumns)
return true;
let hasDifferencesByCaption = filter(definition.data, (def) => this.columns[def.originalIndex].caption != def.caption).length > 0;
this.debug("hasDifferencesByCaption", hasDifferencesByCaption);
return hasDifferencesByCaption;
}
applyColumnReorderingDefinition(definition) {
for (let i = 0; i < this.columns.length; i++) {
let def = find(definition.data, (x) => x.caption == this.columns[i].caption);
if (!def)
continue;
this.columns[i].index = def.userIndex;
this.debug(this.columns[i].caption, this.columns[i].index);
}
this.columns = orderBy(this.columns, (x) => x.index);
}
updateColumnReorderingDefinition() {
if (!this.userPreferencesKey)
return;
let definition = this.getColumnReorderingDefinition();
for (let i = 0; i < this.columns.length; i++) {
this.columns[i].index = i;
let def = definition.data.find((x) => x.caption == this.columns[i].caption);
if (!def)
continue;
def.userIndex = i;
}
this._columnDefinitions = definition;
localStorage.setItem(this.userPreferencesKey, JSON.stringify(definition));
}
getColumnReorderingDefinitionFrom(column) {
if (!this.userPreferencesKey)
return undefined;
let definition = this.getColumnReorderingDefinition();
if (!definition)
return undefined;
let def = definition.data.find((x) => x.caption == column.caption);
if (!def)
return undefined;
return def;
}
filterColumnsThatShouldBeVisible() {
this.columns = this._internalColumns.filter((x) => x.visible);
}
debug(message, ...params) {
if (!this.debugMode)
return;
console.log(message, ...params);
}
}
DataGridComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DataGridComponent, deps: [{ token: DATAGRID_CONFIG, optional: true }, { token: i0.IterableDiffers }, { token: i1.BsModalService }, { token: i0.Renderer2 }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
DataGridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DataGridComponent, selector: "datagrid", inputs: { debugMode: "debugMode", tableId: "tableId", columns: "columns", emptyResultsMessage: "emptyResultsMessage", infoMessage: "infoMessage", animated: "animated", striped: "striped", bordered: "bordered", hoverEffect: "hoverEffect", responsive: "responsive", showCheckboxColumn: "showCheckboxColumn", showSelectAllCheckbox: "showSelectAllCheckbox", selectAllPages: "selectAllPages", checkBoxMode: "checkBoxMode", showSummaries: "showSummaries", allowExports: "allowExports", exportButtonLabel: "exportButtonLabel", exportedFileName: "exportedFileName", exportedExcelSheetName: "exportedExcelSheetName", initialColumnToSort: "initialColumnToSort", initialSortDirection: "initialSortDirection", mode: "mode", totalItems: "totalItems", itemsPerPage: "itemsPerPage", maxSize: "maxSize", boundaryLinks: "boundaryLinks", directionLinks: "directionLinks", rotate: "rotate", showActionsColumn: "showActionsColumn", showInfos: "showInfos", actionsColumnCaption: "actionsColumnCaption", actionsColumnWidth: "actionsColumnWidth", firstText: "firstText", previousText: "previousText", nextText: "nextText", lastText: "lastText", autoFitMode: "autoFitMode", allowColumnResize: "allowColumnResize", allowColumnFilters: "allowColumnFilters", allowColumnReorder: "allowColumnReorder", fixedHeader: "fixedHeader", minHeight: "minHeight", maxHeight: "maxHeight", userPreferencesKey: "userPreferencesKey", filterPlaceholder: "filterPlaceholder", filterPlacement: "filterPlacement", boundedExportCallback: "boundedExportCallback", data: "data" }, outputs: { OnSelectionChanged: "OnSelectionChanged", OnRowSelected: "OnRowSelected", OnRowRendered: "OnRowRendered", OnPaginate: "OnPaginate", OnSort: "OnSort", OnColumnFiltered: "OnColumnFiltered" }, queries: [{ propertyName: "actionsColumnTemplate", first: true, predicate: ActionsColumnDirective, descendants: true, read: TemplateRef, static: true }], viewQueries: [{ propertyName: "paginator", first: true, predicate: ["paginator"], descendants: true }], ngImport: i0, template: "<div class=\"ui-hero-datagrid\">\n <div \n [ngClass]=\"{\n 'table-responsive': responsive,\n 'fixed-header': fixedHeader\n }\"\n [ngStyle]=\"{\n 'max-height.px': fixedHeader && maxHeight > 0 ? maxHeight : 'auto',\n 'min-height.px': fixedHeader && minHeight > 0 ? minHeight : 'auto'\n }\">\n <table [id]=\"tableId\" class=\"table\" [ngClass]=\"{\n 'table-striped': striped,\n 'table-bordered': bordered,\n 'table-hover': hoverEffect,\n 'table-animated': animated && initialRenderApplied && !isResizing,\n 'table-animating': animating && initialRenderApplied,\n 'table-fixed': autoFitMode == 1 || autoFitMode == 2,\n 'table-not-resizing': !isResizing,\n 'd-none': !initialRenderApplied\n }\">\n <thead>\n <tr>\n <th class=\"\" *ngIf=\"showCheckboxColumn && gridData?.hasData\" style=\"width: 50px;\">\n\n <div class=\" custom-control custom-switch\" *ngIf=\"checkBoxMode == 1 && showSelectAllCheckbox\">\n <input type=\"checkbox\" class=\"custom-control-input\" [id]=\"'customSwitchDataGrid' + tableId \" [(ngModel)]=\"selectAll\" (change)=\"OnSelectAllChanged()\" > \n <label class=\"custom-control-label\" [for]=\"'customSwitchDataGrid' + tableId\"></label> \n </div>\n\n <input type=\"checkbox\" [(ngModel)]=\"selectAll\" (change)=\"OnSelectAllChanged()\" *ngIf=\"checkBoxMode == 0 && showSelectAllCheckbox\" />\n </th>\n <th class=\"action text-center\" *ngIf=\"showActionsColumn\" [ngStyle]=\"{'width': actionsColumnWidth}\">{{actionsColumnCaption}}</th>\n <th *ngFor=\"let column of columns; let i = index;\" \n (click)=\"ToogleSorting(column)\" \n class=\"column {{column.captionClasses}}\" \n [draggable]=\"false\"\n [ngStyle]=\"{'width': column.width}\" \n [ngClass]=\"{\n 'sortable': column.sortable,\n 'sorting': column.sort?.sorting,\n 'asc': column.sort?.sortDirection == 'asc',\n 'desc': column.sort?.sortDirection == 'desc'\n }\">\n <div class=\"d-flex justify-content-between align-items-center\"> \n <div class=\"flex-grow-1\" \n [ngClass]=\"{'text-center': column.captionAlignment == 1, 'text-right': column.captionAlignment == 2}\" \n [draggable]=\"allowColumnReorder && !isResizing\" \n (mousedown)=\"OnColumnMouseDown($event, i)\"\n [innerHtml]=\"column.renderCaption ? column.renderCaption() : column.caption\"> \n </div>\n <i class=\"fa fa-sort ml-1\" *ngIf=\"column.sortable && !column.sort?.sorting && gridData?.hasData\"></i>\n <i class=\"fa fa-sort-amount-asc ml-1\" *ngIf=\"column.sortable && column.sort?.sorting && column.sort?.sortDirection == 'asc' && gridData?.hasData\"></i>\n <i class=\"fa fa-sort-amount-desc ml-1\" *ngIf=\"column.sortable && column.sort?.sorting && column.sort?.sortDirection == 'desc' && gridData?.hasData\"></i>\n\n <button type=\"button\" class=\"btn btn-sm btn-filter ml-2 mr-1\" *ngIf=\"allowColumnFilters && column.filterable && data?.length > 0\"\n [popover]=\"popFilters\" triggers=\"\" [isOpen]=\"column.isFiltersOpenned\" [placement]=\"filterPlacement\" [adaptivePosition]=\"false\" container=\"body\" (click)=\"OnColumnFilterClick($event, column)\" [ngClass]=\"{\n 'btn-primary': column.simpleFilter || column.customFilters?.length > 0\n }\">\n <i class=\"fa fa-filter\"></i>\n </button>\n\n <ng-template #popFilters>\n <ui-column-filter \n [column]=\"column\" \n [data]=\"data\" \n [filterPlaceholder]=\"filterPlaceholder\" \n [emptyResultsMessage]=\"emptyResultsMessage\" \n (onChange)=\"OnFiltersChange($event)\">\n </ui-column-filter>\n </ng-template>\n </div>\n <div class=\"resizer\" *ngIf=\"allowColumnResize\" (mousedown)=\"OnResizerMouseDown($event)\"></div>\n </th>\n </tr>\n </thead>\n <tbody *ngIf=\"sortApplied\">\n <tr *ngFor=\"let row of gridData.rows; let rowIndex = index;\" [ngClass]=\"row.ngClass\">\n <td class=\"\" *ngIf=\"showCheckboxColumn && gridData?.hasData && checkBoxMode == 1\">\n <div class=\"custom-control custom-switch\" style=\"overflow: initial !important\">\n <input type=\"checkbox\" class=\"custom-control-input\" [id]=\"'customSwitchDataGrid' + rowIndex + tableId\" [(ngModel)]=\"row.selected\" (change)=\"OnRowSelectedChanged(row, rowIndex)\" > \n <label class=\"custom-control-label\" [for]=\"'customSwitchDataGrid' + rowIndex + tableId\"></label> \n </div> \n </td>\n <td class=\"text-center checkbox-column\" *ngIf=\"showCheckboxColumn && gridData?.hasData && checkBoxMode == 0\">\n \n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"OnRowSelectedChanged(row, rowIndex)\" *ngIf=\"checkBoxMode == 0 \" />\n </td>\n <td class=\"action text-center\" *ngIf=\"showActionsColumn\">\n <ng-container \n [ngTemplateOutlet]=\"actionsColumnTemplate\"\n [ngTemplateOutletContext]=\"{\n row: row.model,\n rowIndex: rowIndex\n }\">\n </ng-container>\n </td>\n <td *ngFor=\"let column of columns; let columnIndex = index;\" \n class=\"{{column.dataClasses}}\" \n [ngClass]=\"{\n 'text-center': column.dataAlignment == 1,\n 'text-right': column.dataAlignment == 2\n }\"> \n <span \n [title]=\"column.enableTooltip ? row.columns[columnIndex].value : ''\"\n [innerHtml]=\"row.columns[columnIndex]?.value\"\n (click)=\"HandleColumnClick(row, row.columns[columnIndex].value, rowIndex, column)\">\n </span>\n </td>\n </tr>\n <tr *ngIf=\"showSummaries && HasSummarizableColumns()\" class=\"summaries\">\n <td *ngIf=\"showCheckboxColumn && gridData?.hasData\"></td>\n <td *ngIf=\"showActionsColumn\"></td>\n <td *ngFor=\"let column of columns; let columnIndex = index;\" class=\"{{column.dataClasses}}\" [ngClass]=\"{\n 'text-center': column.dataAlignment == 1,\n 'text-right': column.dataAlignment == 2\n }\"> \n <span *ngIf=\"column.summarizable\">{{column.summaryPrefix}}{{RenderColumnSummary(column) | number:'1.2-2'}}</span>\n </td>\n </tr>\n </tbody>\n <tfoot *ngIf=\"sortApplied && (!gridData || !gridData.hasData)\">\n <tr>\n <td class=\"empty-results text-center p-3\" [attr.colspan]=\"columns?.length + (showActionsColumn ? 1 : 0) + (showCheckboxColumn && gridData?.hasData ? 1 : 0)\">\n <p class=\"mb-0\">{{emptyResultsMessage}}</p>\n </td>\n </tr>\n </tfoot>\n </table>\n\n <div class=\"loading-box\" *ngIf=\"!sortApplied\">\n <spinner></spinner>\n </div>\n </div>\n\n <div class=\"d-flex align-items-center flex-wrap-reverse mt-3\" *ngIf=\"showInfos && gridData?.hasData\">\n <div class=\"d-flex align-items-center flex-wrap-reverse justify-content-center\">\n <div class=\"d-flex align-items-center flex-wrap\">\n <div class=\"export-actions mr-3 my-1\" *ngIf=\"allowExports\">\n <div class=\"btn-group\" dropdown>\n <button dropdownToggle type=\"button\" class=\"btn btn-primary dropdown-toggle\">\n <i class=\"fa fa-external-link\"></i> {{exportButtonLabel}} <span class=\"caret\"></span>\n </button>\n <ul *dropdownMenu class=\"dropdown-menu\" role=\"menu\">\n <li role=\"menuitem\"><a class=\"dropdown-item\" href=\"#\" (click)=\"ExportToExcel($event)\"><i class=\"fa fa-file-excel-o\"></i> Excel</a></li>\n </ul>\n </div>\n </div>\n </div>\n <div class=\"info mr-3 my-1\">\n <span>{{GetInfo()}}</span>\n </div>\n </div>\n \n <div class=\"pagination ml-auto\">\n <pagination #paginator\n [(ngModel)]=\"currentPage\"\n [totalItems]=\"totalItems\"\n [itemsPerPage]=\"itemsPerPage\"\n [boundaryLinks]=\"boundaryLinks\"\n [directionLinks]=\"directionLinks\"\n [maxSize]=\"maxSize\"\n [rotate]=\"rotate\"\n [firstText]=\"firstText\"\n [lastText]=\"lastText\"\n [nextText]=\"nextText\"\n [previousText]=\"previousText\"\n (pageChanged)=\"PageChanged($event)\">\n </pagination>\n </div>\n </div> \n</div>\n", styles: [":host{display:flex;flex-direction:column;flex:1 0 auto}.ui-hero-datagrid{position:relative;display:flex;flex-direction:column;flex:1 0 auto}.ui-hero-datagrid table{margin-bottom:0}.ui-hero-datagrid table th{position:relative}.ui-hero-datagrid table th>div>div{flex-shrink:0;-webkit-user-select:none;user-select:none}.ui-hero-datagrid table th .resizer{position:absolute;cursor:col-resize;top:0;right:0;width:6px;height:100%;background:repeating-linear-gradient(45deg,transparent,transparent 2px,rgba(0,0,0,.05) 2px,rgba(0,0,0,.05) 4px)}.ui-hero-datagrid table th:hover .resizer{background:repeating-linear-gradient(45deg,transparent,transparent 2px,rgba(0,0,0,.2) 2px,rgba(0,0,0,.2) 4px)}.ui-hero-datagrid table td,.ui-hero-datagrid table th{overflow:hidden;vertical-align:middle}.ui-hero-datagrid table td>*{word-break:break-word}.ui-hero-datagrid table th.sortable{cursor:pointer}.ui-hero-datagrid table th.checkbox-column input[type=checkbox]{margin:0;width:20px;height:20px;vertical-align:middle}.ui-hero-datagrid table td.checkbox-column input[type=checkbox]{margin:0 auto;width:20px;height:20px;vertical-align:middle}.ui-hero-datagrid table tr.sum