import { Component, OnInit, Input, NgModule, forwardRef, Output, EventEmitter, ViewEncapsulation, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, AfterViewInit, OnDestroy } from '@angular/core'; import { CommonModule, DatePipe, formatDate } from '@angular/common'; import { FilterMetadata, SelectItem } from 'primeng/api'; import { ButtonModule } from 'primeng/button'; import { TableModule, Table } from 'primeng/table'; import { OverlayPanelModule } from 'primeng/overlaypanel'; import { CheckboxModule } from 'primeng/checkbox'; import { SharedModule } from 'primeng/components/common/shared'; import { InputTextModule } from 'primeng/inputtext'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { EtableColumn } from 'ekangularbase/src/interface/EtableColumn'; import { CurrencyMaskModule } from 'ng2-currency-mask'; import * as xlsx from 'xlsx'; // Angular-Slickgrid start import { AngularGridInstance, Aggregators, Column, DelimiterType, FieldType, FileType, Filters, Formatters, GridOption, Grouping, GroupTotalFormatters, SortDirectionNumber, Sorters, OnEventArgs, AngularSlickgridModule, Formatter, Editors, GridService, AngularUtilService, GridOdataService, OdataOption, GroupingGetterFunction, } from 'angular-slickgrid'; import { AuditTrailListModule, AuditTrailListComponent } from 'ekangularbase/src/audit-trail-list/audit-trail-list.component'; import { DropdownModule } from 'primeng/dropdown'; import { MultiSelectModule } from 'primeng/multiselect'; import { ProgressSpinnerModule } from 'primeng/progressspinner'; import { EntityStatus } from 'ekangularbase/src/interface/entity-status'; import { BlockUIModule } from 'primeng/blockui'; import { PanelModule } from 'primeng/panel'; import * as $ from 'jquery'; import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs'; import { ekThousandSeparatorFormatter, numberWithCommas } from 'ekangularbase/src/ek-components/etable/formatter/ekThousandSeparatorFormatter'; import { EtableFunction } from 'ekangularbase/src/interface/EtableFunction'; import { ListboxModule } from 'primeng/primeng'; // Angular-Slickgrid end // export const Etable_VALUE_ACCESSOR: any = { // provide: NG_VALUE_ACCESSOR, // useExisting: forwardRef(() => EtableComponent), // multi: true // }; @Component({ selector: 'e-table', templateUrl: './etable.component.html', encapsulation: ViewEncapsulation.None, styleUrls: ['./etable.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) export class EtableComponent implements OnInit, AfterViewInit, OnDestroy { selectAll = false; boolHeaderOption: SelectItem[]; lazyLoadingChangesSubscription: Subscription; lazyLoadingChanges: BehaviorSubject; selectedCols: any[]; constructor(private cd: ChangeDetectorRef, private angularUtilService: AngularUtilService, public datepipe: DatePipe) { this.loadSlickGrid = false; this.loading = false; this.lazyLoadingChanges = new BehaviorSubject(''); this.boolHeaderOption = [ { value: null, label: 'All' }, { value: true, label: 'Yes' }, { value: false, label: 'No' }, ]; } // Angular-Slickgrid start gridRowCountFilter = 0; private _commandQueue = []; angularGrid: AngularGridInstance; columnDefinitions: Column[]; columnDefinitionsVisible: Column[]; // dataset: any[]; dataviewObj: any; draggableGroupingPlugin: any; durationOrderByCount = false; gridObj: any; gridOptions: GridOption; processing = false; selectedGroupingFields: Array = ['', '', '']; gridService: GridService; // Angular-Slickgrid end @ViewChild('dt', { static: false }) dt: Table; @Input() strTableName = ''; @Input() tableType = ''; @Input() columns: EtableColumn[]; @Input() func: EtableFunction[]; @Input() value: any[]; @Input() colHeader: any[]; @Input() footerColumns: any[]; @Input() footerObjectlist: any[]; @Input() paginator: boolean; @Input() scrollHeight = '400px'; @Input() rows: number; // @Input() first: number = 0; @Input() pageLinks = 5; @Input() rowsPerPageOptions: number[]; @Input() sortMode = 'single'; // @Input() resetPageOnSort: boolean = true; @Input() selectionMode: string; @Input() scrollable: boolean; @Input() responsive: boolean; // @Input() contextMenu: any; @Input() resizableColumns: boolean; @Input() columnResizeMode = 'fit'; // @Input() reorderableColumns: boolean; @Input() loading = false; @Input() allowGrouping = false; @Input() allowExportToExcel = false; @Input() showTotalRecord = true; @Input() slickMinHeight = 480; @Input() slickMaxHeight = 1024; @Input() slickBottomPadding = 30; @Input() logColumnList: string[] = []; @Input() gridId = 'grid19'; @Input() selection: any; @Input() hideDeletedButton = true; @Input() isDataFinishLoaded = false; @Input() allowLazyLoading = false; @Input() inActiveStatusList: string[] = [EntityStatus.InActive, EntityStatus.Deleted, EntityStatus.Retired]; @Input() updateCssIdList: string[]; @Input() updateCssClass: string; @Input() defaultHideFilter = true; timerInterval: any; loadSlickGrid = false; filteredValueCount = 0; headerCount = 0; @Output() listEvent = new EventEmitter(); @Output() onRowClickEvent = new EventEmitter(); @Input() funcConditionEvent: (value: any) => boolean; @Input() checkBoxConditionEvent: (value: any) => boolean; @Input() classChangeEvent: (value: any) => string; @Input() iconChangeEvent: (value: any) => string; @Output() lazyLoadingApiCallEvent = new EventEmitter(); @Output() onMenuClickEvent = new EventEmitter(); @Output() onCellClickedEvent = new EventEmitter(); @Output() onCellChangedEvent = new EventEmitter(); @Output() onCellFocusEvent = new EventEmitter(); @Output() onCellKeyPressEvent = new EventEmitter(); @Input() textBoxConditionEvent: (value: any) => boolean; ngOnInit() { if (this.tableType === 'SlickGrid') { this.loading = false; this.timerInterval = setInterval(() => { if (this.isDataFinishLoaded && this.isDataFinishLoaded === true) { clearInterval(this.timerInterval); this.defineGrid(); this.defineGridOption(); this.loadSlickGrid = true; this.detectChanges(); } }, 100); } } ngAfterViewInit() { if (this.tableType === 'SlickGrid' && this.allowLazyLoading === false) { this.loading = true; } } detectChanges(event = null) { console.log('detectChanges', event); try { if (this.tableType === 'SlickGrid') { if (event !== null) { if (event['name'] && event['name'] === 'onDelete') { this.selectRow(event); } if (event['selectAllCheckBox'] !== undefined) { this.updateSelectAllCheckBox(event); } if (event['lazyLoadingChanges']) { this.lazyLoadingChanges.next(event['lazyLoadingChanges']); } } this.cd.detectChanges(); // this.checkNoData(); // this.resetSlickGrid(); this.render(); } else if (this.tableType === '') { if (event !== null) { if (event['selectAllCheckBox'] !== undefined) { this.bindingSelectedCols(); } } setTimeout(() => { console.log('gridId', this.gridId); console.log('this.value.length', this.value); this.filteredValueCount = this.value ? this.value.length : 0; const totalFuncs = this.func.filter(s => s.visible === true); const totalCols = this.columns.filter(s => s.visible === true); this.headerCount = totalFuncs.length + totalCols.length; this.cd.detectChanges(); }, 200); } } catch (error) { console.log(error); } } bindingSelectedCols() { console.log('bindingSelectedCols', this.columns); this.selectedCols = []; if (this.arrayOfObjectIsNull(this.columns)) { return; } this.columns.forEach(c => { if (c.visible === true) { this.selectedCols.push(c); } }); this.cd.detectChanges(); } updateSelectAllCheckBox(event) { try { console.log('updateSelectAllCheckBox', event); console.log('this.func', this.func); const cb = this.func.find(s => s.funcType === 'checkbox'); if (!cb || cb === null) { return; } if (this.angularGrid) { const allColumns = this.angularGrid.gridService.getAllColumnDefinitions(); console.log('allColumns', allColumns); allColumns[0].header.buttons[0]['cssClass'] = 'fa fa-square header-checkbox'; // this.columnDefinitions = this.columnDefinitions.slice(); } // this.resetSlickGrid(); } catch (error) { console.log(error); } } selectRow(event) { this.dt._selection = event.data; this.dt.tableService.onSelectionChange(); if (this.dt.isStateful()) { this.dt.saveState(); } } seachTextChange(event: any) { setTimeout(() => { this.cd.detectChanges(); }, 1000); } exportCSV() { this.dt.exportCSV(); } emitList(args) { this.columns.forEach(c => c.searchText = null); if (this.tableType === '') { this.dt.reset(); } else if (this.tableType === 'SlickGrid') { // try { // const cb = this.func.find(s => s.funcType === 'checkbox'); // if (cb && cb !== null) { // args.allColumns[0].header.buttons[0].cssClass = 'fa fa-square header-checkbox'; // } // } catch (error) { // console.log(error); // } } this.listEvent.emit(); this.cd.detectChanges(); } resetTable() { if (this.tableType === 'SlickGrid') { this.resetSlickGrid(); } else { this.resetPtable(); } } resetPtable() { this.dt.reset(); this.cd.detectChanges(); } resetSlickGrid() { if (this.angularGrid) { this.defineGrid(); // this.defineGridOption(); this.angularGrid.slickGrid.setColumns(this.columnDefinitions); } } toDecimal(input: number | string, minDecimal?: number, maxDecimal?: number, isRounding = true): string { if (input === undefined || input === null || input === '') { input = 0; } if (isNaN(+input)) { return 'NaN'; } const valStr = String(input); const parts = valStr.split('.'); let parts1 = parts[0]; let parts2 = ''; if (parts.length === 2) { parts2 = parts[1]; } if (minDecimal && minDecimal > parts2.length) { while (minDecimal > parts2.length) { parts2 += '0'; } } if (maxDecimal && maxDecimal > 0 && maxDecimal < parts2.length) { const lastDigit = parseInt(parts2[maxDecimal], 10); let last2ndDigit = parseInt(parts2[maxDecimal - 1], 10); if (isRounding && lastDigit >= 5) { last2ndDigit += 1; } parts2 = parts2.substr(0, maxDecimal - 1) + last2ndDigit.toString(); } if (maxDecimal === 0 && parts2.length > 0) { const lastDigit = parseInt(parts2[0], 10); let last2ndDigit = parseInt(parts1[parts1.length - 1], 10); if (isRounding && lastDigit >= 5) { last2ndDigit += 1; } parts1 = parts1.substr(0, parts1.length - 1) + last2ndDigit.toString(); parts2 = ''; } let result = parts2 === '' ? '' : '.' + parts2; result = parts1 + result; return result; } exportObjList(): any[][] { const result: any[][] = []; const cols = this.columns.filter(s => s.visible); const headerRow: any[] = []; for (let i = 0; i < cols.length; i++) { const column = cols[i]; headerRow.push(column.header); } result.push(headerRow); for (const record of this.value) { const row: any[] = []; for (let i = 0; i < cols.length; i++) { const column = cols[i]; if (column.exportable !== false && column.field) { if (column.isSubObject) { const fields: string[] = []; fields.push(column.field); fields.push(column.subField); const detailField = column.subField; let detailCellData = record[fields[0]] == null ? null : record[fields[0]][detailField]; if (detailCellData != null && detailCellData !== '') { if (column.dataType === 'DateTime' && detailCellData.length >= 10) { detailCellData = String(detailCellData).substring(0, 10); } else if (column.dataType === 'DateTime_ToLocal_General' && detailCellData.length > 10) { const x = new Date(detailCellData.toString() + 'Z').toLocaleString(); detailCellData = formatDate(new Date(x), 'yyyy-MM-dd HH:mm:ss', 'en_US'); } else if (column.dataType === 'Date_ToLocal_General' && detailCellData.length > 10) { const x = new Date(detailCellData.toString() + 'Z').toLocaleString(); detailCellData = formatDate(new Date(x), 'yyyy-MM-dd', 'en_US'); } else if (column.dataType === 'amount_General') { detailCellData = this.toDecimal(detailCellData, 2, 2); } else { detailCellData = String(detailCellData).replace(/"/g, '""'); } } else { if (column.dataType === 'amount_General') { detailCellData = this.toDecimal(detailCellData, 2, 2); } else { detailCellData = ''; } } row.push(detailCellData); } else { let cellData = record[column.field]; if (cellData != null && cellData !== '') { if (column.dataType === 'DateTime' && cellData.length >= 10) { cellData = String(cellData).substring(0, 10); } else if (column.dataType === 'DateTime_ToLocal_General' && cellData.length > 10) { const x = new Date(cellData.toString() + 'Z').toLocaleString(); cellData = formatDate(new Date(x), 'yyyy-MM-dd HH:mm:ss', 'en_US'); } else if (column.dataType === 'Date_ToLocal_General' && cellData.length > 10) { const x = new Date(cellData.toString() + 'Z').toLocaleString(); cellData = formatDate(new Date(x), 'yyyy-MM-dd', 'en_US'); } else if (column.dataType === 'amount_General') { cellData = this.toDecimal(cellData, 2, 2); } else { cellData = String(cellData).replace(/"/g, '""'); } } else { if (column.dataType === 'amount_General') { cellData = this.toDecimal(cellData, 2, 2); } else { cellData = ''; } } row.push(cellData); } } } result.push(row); } if (this.footerObjectlist && this.footerObjectlist.length > 0) { this.footerObjectlist.forEach(o => { const row: any[] = []; let x = -1; for (let index = 0; index < o.config.length; index++) { const colspan = o.config[index].colspan; x += 1; for (let i = 1; i < colspan; i++) { row.push(''); x += 1; } const field = o.config[index].field; const data = o.data[field]; if (data) { if (o.config[index].dataType === 'amount_General') { row.push(this.toDecimal(data, 2, 2)); } else { row.push(data); } } else { row.push(''); } } result.push(row); }); } console.log('exportObjList', result); return result; } exportToExcelPtable() { const ws: xlsx.WorkSheet = xlsx.utils.aoa_to_sheet(this.exportObjList()); const wb: xlsx.WorkBook = xlsx.utils.book_new(); xlsx.utils.book_append_sheet(wb, ws, 'Sheet1'); xlsx.writeFile(wb, 'ExportData.xlsx'); } onHideFilter() { this.defaultHideFilter = !this.defaultHideFilter; } emitonSelectAllClickClick(func, field: string) { func.args = this.selectAll; this.emitOnRowClick(func, field); } emitOnRowClick(row, field: string) { this.onRowClickEvent.emit({ row, field }); } emitFuncCondition(row, func): boolean { try { return this.funcConditionEvent({ row, func }); } catch (error) { return true; } } emitCheckBoxCondition(row, func): boolean { try { return this.checkBoxConditionEvent({ row, func }); } catch (error) { return true; } } emitClassChange(row, func) { try { return this.classChangeEvent({ row, func }); } catch (error) { return ''; } } emitIconChange(row, func) { try { return this.iconChangeEvent({ row, func }); } catch (error) { return true; } } emitOnMenuClick() { this.onMenuClickEvent.emit(); this.cd.detectChanges(); } selectedColsChange() { console.log('selectedCols', this.selectedCols); if (!this.arrayOfObjectIsNull(this.columns)) { this.columns.forEach(c => { c.visible = false; if (!this.arrayOfObjectIsNull(this.selectedCols)) { const se = this.selectedCols.find(s => s.field === c.field); if (se) { c.visible = true; } } }); } this.emitOnMenuClick(); } emitOnCellClicked(event, args) { this.onCellClickedEvent.emit({ event, args }); } emitOnCellChanged(event, args, field) { this.onCellChangedEvent.emit({ event, args, field }); } emitOnCellFocus(event, args, field) { this.onCellFocusEvent.emit({ event, args, field }); } emitOnCellKeyPress(event, args, field) { this.onCellKeyPressEvent.emit({ event, args, field }); } emitTextBoxCondition(row, column, value): boolean { try { return this.textBoxConditionEvent({ row, column, value }); } catch (error) { return true; } } onFilter(event) { console.log('onFilter', event); this.filteredValueCount = event.filteredValue.length; this.cd.detectChanges(); } // Angular-Slickgrid start angularGridReady(angularGrid: AngularGridInstance) { this.angularGrid = angularGrid; this.gridObj = angularGrid.slickGrid; // grid object this.dataviewObj = angularGrid.dataView; this.gridService = angularGrid.gridService; this.checkNoData(); // this.dataviewObj.getItemMetadata = this.updateItemMetadataForDurationOver50(this.dataviewObj.getItemMetadata); this.dataviewObj.getItemMetadata = this.metadata(this.dataviewObj.getItemMetadata, this.inActiveStatusList); this.gridObj.invalidate(); this.gridObj.render(); this.updateRowCssWithId(); if (this.allowGrouping === true) { console.log('setPreHeaderPanelVisibility'); this.gridObj.setPreHeaderPanelVisibility(!this.gridObj.getOptions().showPreHeaderPanel); } if (this.defaultHideFilter === true) { console.log('setHeaderRowVisibility'); this.gridObj.setHeaderRowVisibility(!this.defaultHideFilter); } this.gridRowCountFilter = this.gridObj.getDataLength(); this.getGridRowCountFilter().subscribe((r) => { console.log('getGridRowCountFilter subscribe', r); this.gridRowCountFilter = r; this.checkNoData(); this.cd.detectChanges(); }); } checkNoData() { try { if (!this.value || this.value === null || !Array.isArray(this.value) || this.value.length === 0) { // const gridBody: HTMLCollectionOf = // > document.getElementsByClassName('grid-canvas'); const elementById: HTMLLinkElement = document.getElementById('slick-container-' + this.gridId); const gridBody: HTMLCollectionOf = >elementById.getElementsByClassName('grid-canvas'); if (gridBody && gridBody !== null && gridBody.length > 0) { console.log('gridBody', gridBody); gridBody.item(0).innerHTML = '
"No Data Found"
"No Data Found"
'; } } else { const el = document.querySelector('.slick-no-data-main'); if (el) { el.className += ' slickgrid-hide-nodata'; } } } catch (error) { console.error(error); } } getGridRowCountFilter(): Observable { let totalQuestions: number; const subject = new Subject(); this.dataviewObj.onRowCountChanged .subscribe(function (e, args) { console.log('getGridRowCountFilter', args); totalQuestions = args.current; subject.next(totalQuestions); } ); return subject.asObservable(); } getFormatters(field, func, dataContext): any { switch (field) { case 'onRowSelect': case 'onEdit': { return ``; } case 'onDelete': { return ``; } case 'onAdopterSelect': { if (dataContext && dataContext['polisyCreated'] === true) { return ``; } else { return ``; } } case 'onActivate': { if (dataContext && dataContext['entityStatus'] === 'Active') { return ``; } else { return ``; } } default: { // console.log('Invalid Formatters: ' + field); return ``; } } } getFieldType(cd, columns): any { switch (columns.dataType) { case 'number_General': { cd.filter = { model: Filters.compoundInput }; cd.type = FieldType.number; cd.formatter = ekThousandSeparatorFormatter; cd.params = { minDecimalPlaces: 1, maxDecimalPlaces: 5 }; cd.cssClass = 'etable-number-general ' + columns.class; break; } case 'amount_General': { cd.filter = { model: Filters.compoundInput }; cd.type = FieldType.number; cd.formatter = ekThousandSeparatorFormatter; cd.params = { minDecimalPlaces: 2, maxDecimalPlaces: 2 }; cd.cssClass = 'etable-amount-general ' + columns.class; break; } case 'int_General': { cd.filter = { model: Filters.compoundInput }; cd.type = FieldType.number; cd.formatter = ekThousandSeparatorFormatter; cd.params = { minDecimalPlaces: 0, maxDecimalPlaces: 0 }; cd.cssClass = 'etable-number-general ' + columns.class; break; } case 'Date_General': { cd.filter = { model: Filters.compoundDate }; cd.type = FieldType.date; cd.formatter = Formatters.dateIso; cd.cssClass = columns.class; break; } case 'DateTime': { cd.filter = { model: Filters.compoundDate }; cd.type = FieldType.date; cd.formatter = Formatters.dateTimeIso; cd.cssClass = columns.class; break; } case 'time': { cd.filter = { model: Filters.compoundInputText }; // cd.type = FieldType.dateTimeIso; cd.formatter = this.myTimeFormatter; cd.cssClass = columns.class; break; } case 'Date_ToLocal_General': { cd.filter = { model: Filters.compoundInputText }; // cd.type = FieldType.dateTimeIso; cd.formatter = this.myDateToLocalFormatter; cd.cssClass = columns.class; break; } case 'DateTime_ToLocal_General': { cd.filter = { model: Filters.compoundInputText }; // cd.type = FieldType.dateTimeIso; cd.formatter = this.myDateTimeToLocalFormatter; cd.cssClass = columns.class; break; } case 'DateTime_MonthName': { cd.filter = { model: Filters.compoundInputText }; cd.formatter = this.myDateToMonthNameFormatter; cd.cssClass = columns.class; break; } case 'number': { cd.filter = { model: Filters.compoundInput }; cd.type = FieldType.number; cd.cssClass = columns.class; break; } case 'currency': { cd.filter = { model: Filters.compoundInput }; cd.type = FieldType.number; cd.cssClass = columns.class; break; } case 'uppercase': { cd.filter = { model: Filters.compoundInputText }; cd.formatter = Formatters.uppercase; cd.cssClass = columns.class; break; } case 'lowercase': { cd.filter = { model: Filters.compoundInputText }; cd.formatter = Formatters.lowercase; cd.cssClass = columns.class; break; } case 'boolean': { cd.filterable = true; cd.type = FieldType.boolean; cd.filter = { model: Filters.singleSelect, collection: [{ value: '', label: 'All' }, { value: true, label: 'Yes' }, { value: false, label: 'No' }], }; cd.formatter = this.checkmarkFormatter; cd.cssClass = columns.class; break; } case 'hyperlink': { cd.filter = { model: Filters.compoundInputText }; cd.formatter = Formatters.hyperlink; cd.params = { hyperlinkText: 'Company Website', hyperlinkUrl: 'http://www.somewhere.com' }; cd.cssClass = columns.class; break; } case 'textBox': { cd.filter = { model: Filters.compoundInputText }; cd.formatter = this.myCustomTextBoxFormatter; // cd.cssClasses = 'form-control'; cd.cssClass = columns.class; cd.type = FieldType.string; cd.editor = { model: Editors.text, // required: true, // minValue: 0, // elementOptions: { // onClick: (event, args) => { // // here i want to write some code which can trigger to grid to start update // console.log(event); // console.log(args); // } // } }; break; } default: { // console.log("Invalid FieldType"); cd.filter = { model: Filters.compoundInputText }; cd.type = FieldType.string; cd.cssClass = columns.class; break; } } return cd; } onCellClicked(event, args) { console.log(event); console.log(args); // const fadingDelay = 2000; // in milliseconds // // you can pass an optional fading delay (1500ms by default) // this.gridService.highlightRow(args.row, fadingDelay); this.emitOnCellClicked(event, args); } onCellChanged(event, args) { console.log(event); console.log(args); this.emitOnCellChanged(event, args, ''); } onCellFocus(event, args) { this.emitOnCellFocus(event, args, ''); } onCellKeyPress(event, args) { this.emitOnCellKeyPress(event, args, ''); } toggleCompletedProperty(item) { // toggle property if (typeof item === 'object') { // item.completed = !item.completed; // simulate a backend http call and refresh the grid row after delay setTimeout(() => { this.angularGrid.gridService.updateItemById(item.id, item, { highlightRow: false }); }, 250); } } customEnableButtonFormatter: Formatter = (row: number, cell: number, value: any, columnDef: Column, dataContext: any, grid: any) => { try { const c = this.func.find((v, i, o) => v.function === columnDef.field); // console.log(c); if (!this.emitCheckBoxCondition(dataContext, c)) { return ''; } let field = 'isSelected'; if (c.field) { field = c.field; } return ` `; } catch (error) { console.log('customEnableButtonFormatter', error); return ''; } } customImgFormatter: Formatter = (row: number, cell: number, value: any, columnDef: Column, dataContext: any, grid: any) => { const c = this.func.find((v, i, o) => v.function === columnDef.field); if (!(dataContext[c.function] && dataContext[c.function] !== '')) { return ` `; } const d = dataContext[c.function]; const empImgSrc = c.url + d; return ` `; } customAuditLogListFormatter: Formatter = (row: number, cell: number, value: any, columnDef: Column, dataContext: any, grid: any) => { const h = dataContext['hasChanges']; const v = dataContext['hasChanges'] === true; if (v) { return ` `; } else { return ''; } } myCustomFuncFormatter: Formatter = (row, cell, value, columnDef: Column, dataContext) => { // you can return a string of a object (of type FormatterResultObject), the 2 types are shown below const c = this.func.find((v, i, o) => v.function === columnDef.field); // console.log(c); if (!this.emitFuncCondition(dataContext, c)) { return ''; } if (this.hideDeletedButton && c.function === 'onDelete' && dataContext['entityStatus'] === EntityStatus.Deleted) { return ''; } // return Formatters.editIcon; // return { text: editIconFormatter}; // return { text: editIconFormatter, addClasses: 'lightblue', toolTip: 'Freezing' }; // return ``; // return { text: '', addClasses: 'lightblue', toolTip: 'Freezing' }; return this.getFormatters(columnDef.field, c, dataContext); } render() { console.log('render()'); if (this.gridObj) { console.log('this.gridObj.getOptions().gridMenu.hideTogglePreHeaderCommand', this.gridObj.getOptions().gridMenu.hideTogglePreHeaderCommand); console.log('this.gridObj.getOptions().showPreHeaderPanel', this.gridObj.getOptions().showPreHeaderPanel); this.gridObj.invalidate(); this.gridObj.render(); } } insertSlickGrid(item) { this.dataviewObj.addItem(item); // this.angularGrid.gridService.addItem(item); } myCustomTextBoxFormatter: Formatter = (row, cell, value, columnDef: Column, dataContext) => { // return ''; // return ''; value = '' + value + ''; return value; } myTimeFormatter: Formatter = (row, cell, value, columnDef: Column, dataContext) => { if (!value) { return ''; } try { const x = value.toString().substring(0, 5); return x; } catch (error) { return value; } } myDateTimeToLocalFormatter: Formatter = (row, cell, value, columnDef: Column, dataContext) => { if (!value) { return ''; } try { const x = new Date(value.toString() + 'Z'); const y = this.datepipe.transform(x, 'yyyy-MM-dd HH:mm:ss'); return y; } catch (error) { return value; } } myDateToMonthNameFormatter: Formatter = (row, cell, value, columnDef: Column, dataContext) => { if (!value) { return ''; } try { const x = new Date(value.toString() + 'Z'); const y = this.datepipe.transform(x, 'MMM y'); return y.toUpperCase(); } catch (error) { return value; } } myDateToLocalFormatter: Formatter = (row, cell, value, columnDef: Column, dataContext) => { if (!value) { return ''; } try { const x = new Date(value.toString() + 'Z'); const y = this.datepipe.transform(x, 'yyyy-MM-dd'); return y; } catch (error) { return value; } } checkmarkFormatter: Formatter = (row: number, cell: number, value: any, columnDef: Column, dataContext: any) => { return this.parseBoolean(value) ? `` : ''; } parseBoolean(input: any): boolean { return /(true|1)/i.test(input + ''); } metadata(old_metadata, inActiveStatusList: string[]) { return function (row) { const item = this.getItem(row); const meta = old_metadata(row) || {}; if (item) { // Make sure the "cssClasses" property exists meta.cssClasses = meta.cssClasses || ''; const inActive = inActiveStatusList.includes(item.entityStatus); if (inActive === true) { meta.cssClasses += ' slickgrid-inactive-tr'; } // if (item.qty < 1) { // If the quantity (qty) for this item less than 1 // meta.cssClasses += ' out-of-stock'; // add a class of "out-of-stock" to the row element. // } /* Here is just a random example that will add an HTML class to the row element that is the value of your row's "rowClass" property. Be careful with this as you may run into issues if the "rowClass" property isn't a string or isn't a valid class name. */ // if (item.rowClass) { // const myClass = ' ' + item.rowClass; // meta.cssClasses += myClass; // } } return meta; }; } updateRowCssWithId() { console.log('updateCssIdList', this.updateCssIdList); if (this.arrayOfObjectIsNull(this.updateCssIdList)) { return; } this.dataviewObj.getItemMetadata = this.exeUpdateRowCssWithId(this.dataviewObj.getItemMetadata, this.updateCssClass, this.updateCssIdList); this.gridObj.invalidate(); this.gridObj.render(); } exeUpdateRowCssWithId(previousItemMetadata: any, newCssClass: string, ids: string[]) { return (rowNumber: number) => { const item = this.dataviewObj.getItem(rowNumber); let meta = { cssClasses: '' }; if (typeof previousItemMetadata === 'object') { meta = previousItemMetadata(rowNumber); } if (meta && item) { const found = ids.find(id => id === item.id); if (found && found !== null) { meta.cssClasses = (meta.cssClasses || '') + ' ' + newCssClass; } } return meta; }; } UpdateAllTotals(args) { // this.gridOptions.createFooterRow = true; // this.gridOptions.showFooterRow = true; // this.gridOptions.footerRowHeight = 21; // this.render(); let columnIdx = this.gridObj.getColumns().length; while (columnIdx--) { if (args.allColumns[columnIdx].type && args.allColumns[columnIdx].type === 5) { this.UpdateTotal(columnIdx, args.allColumns[columnIdx].field); } } } UpdateTotal(cell, field) { try { const col = this.columns.find(c => c.field === field); if (this.objectIsNull(col)) { return; } const columnId = this.gridObj.getColumns()[cell].id; const columnFeild = this.gridObj.getColumns()[cell].field; let total = 0; let i = this.value.length; while (i--) { total += (+this.value[i][columnFeild] || 0); } let strTotal = ''; switch (col.dataType) { case 'number_General': { strTotal = numberWithCommas(total, 1, 5); break; } case 'amount_General': { strTotal = numberWithCommas(total, 2, 2); break; } case 'int_General': { strTotal = numberWithCommas(total, 0, 0); break; } default: { strTotal = total.toString(); break; } } const columnElement = this.gridObj.getFooterRowColumn(columnId); columnElement.innerHTML = '' + strTotal + ''; } catch (error) { console.log(error); } } bindFooter() { if (!this.footerObjectlist || this.footerObjectlist[0].config.length === 0) { return; } let cell = 0; const i = this.gridObj.getColumns().length; while (cell < i) { try { const columnId = this.gridObj.getColumns()[cell].id; // const columnFeild = this.gridObj.getColumns()[cell].field; const col = this.columns.find(s => s.id === columnId); const fotterConfig = this.footerObjectlist[0].config.find(s => s.name === col.colFooter[0]); const fotterData = this.footerObjectlist[0].data[fotterConfig.field]; const columnElement = this.gridObj.getFooterRowColumn(columnId); columnElement.innerHTML = '' + fotterData + ''; } catch (error) { console.log(error); } cell++; } } getHeader(colHeader: string[]): string { if (this.allowGrouping) { return null; } if (!this.colHeader || this.colHeader.length === 0) { return null; } const h = this.colHeader[0].find(s => s.name === colHeader[0]); return h.display; } /* Define grid Options and Columns */ defineGrid() { let i = 0; this.columnDefinitions = []; this.columnDefinitionsVisible = []; if (this.func !== undefined) { this.func.forEach(s => { if (s.visible) { if (s.funcType === 'checkbox') { s.id = 'func_' + i.toString(); let field = 'isSelected'; if (s.field) { field = s.field; } const cd = { id: s.id, field: s.function, name: s.header || '', columnGroup: '', excludeFromHeaderMenu: true, formatter: this.customEnableButtonFormatter, minWidth: s.minWidth ? s.minWidth : 30, maxWidth: s.maxWidth ? s.maxWidth : 30, headerCssClass: (s.headerCssClass && s.headerCssClass !== '') ? s.headerCssClass : 'vertical-text-header-checkbox', header: s.showSelectAll !== false ? { buttons: [ { cssClass: 'fa fa-square header-checkbox', command: 'toggle-checkbox', tooltip: 'Select All', // showOnHover: true, } ] } : null, // use onCellClick OR grid.onClick.subscribe which you can see down below onCellClick: (e: Event, args: OnEventArgs) => { try { if (args.dataContext[field]) { args.dataContext[field] = false; } else { args.dataContext[field] = true; } this.toggleCompletedProperty(args && args.dataContext); console.log(args); if (this.emitCheckBoxCondition(args.dataContext, s)) { this.emitOnRowClick(args.dataContext, s.function); } } catch (error) { console.log(error); } } }; this.columnDefinitions.push(cd); this.columnDefinitionsVisible.push(cd); i++; } else if (s.funcType === 'img') { s.id = 'func_' + i.toString(); const cd = { id: s.id, field: s.function, name: s.header || '', columnGroup: '', excludeFromHeaderMenu: true, formatter: this.customImgFormatter, minWidth: s.maxWidth, maxWidth: s.maxWidth, headerCssClass: s.class, }; this.columnDefinitions.push(cd); this.columnDefinitionsVisible.push(cd); i++; } else if (s.funcType === 'hasChanges') { s.id = 'func_' + i.toString(); const cd = { id: s.id, field: s.function, name: s.header || '', columnGroup: '', excludeFromHeaderMenu: true, // formatter: this.customAuditLogListFormatter, minWidth: 30, maxWidth: 30, headerCssClass: 'vertical-text-header-span', // filter: {}, // queryFieldFilter: 'assignee.id', // queryFieldSorter: 'assignee.name', formatter: () => '', asyncPostRender: this.renderAngularComponent.bind(this), params: { component: AuditTrailListComponent, angularUtilService: this.angularUtilService, complexFieldLabel: 'hasChanges', // for the exportCustomFormatter }, exportCustomFormatter: Formatters.complexObject, }; this.columnDefinitions.push(cd); this.columnDefinitionsVisible.push(cd); i++; } else { s.id = 'func_' + i.toString(); if (s.function === 'onRowSelect' || s.function === 'onEdit') { s.header = 'Detail'; } const cd = { id: s.id, field: s.function, name: s.header || '', columnGroup: '', excludeFromHeaderMenu: true, formatter: this.myCustomFuncFormatter, minWidth: 30, maxWidth: 30, headerCssClass: 'vertical-text-header-span', cssClass: 'slickgrid-col-cell-func', // use onCellClick OR grid.onClick.subscribe which you can see down below onCellClick: (e: Event, args: OnEventArgs) => { console.log(args); // if (confirm('Are you sure edit ' + args.dataContext.title + '?')) { // this.angularGrid.gridService.deleteDataGridItemById(args.dataContext.id); // } // this.onRowEdit(args.dataContext); if (this.emitFuncCondition(args.dataContext, s)) { // this.angularGrid.gridService.highlightRow(args.row, 1500); // this.angularGrid.gridService.setSelectedRow(args.row); this.emitOnRowClick(args.dataContext, s.function); } } }; this.columnDefinitions.push(cd); this.columnDefinitionsVisible.push(cd); i++; } } }); } else { this.func = []; } if (this.columns !== undefined) { const sumCols = this.columns.filter(s => s.sumInGrouping === true); const aggregators = []; sumCols.forEach(s => { aggregators.push(new Aggregators.Sum(s.field)); }); this.columns.forEach(s => { s.id = 'colm_' + i.toString(); let cd = { id: s.id, name: s.header || '', field: s.field, columnGroup: this.getHeader(s.colHeader), minWidth: +s.width || 0, maxWidth: +s.width * 2, headerCssClass: 'eslick-header-span ' + s.headerClass, // cssClass: s.class || '', filterable: true, sortable: true, // type: this.getFieldType(s.dataType), groupTotalsFormatter: null, params: {}, grouping: {}, }; if (s.isSubObject === true) { cd.field = s.field + '.' + s.subField; } if (this.allowGrouping) { // if need to display sum if (sumCols.length > 0) { const sumCol = sumCols.find(c => c.id === s.id); if (!sumCol) { cd.grouping = { getter: s.field, formatter: (g) => s.header + `: ${g.value} (${g.count} items)`, aggregators: aggregators, aggregateCollapsed: false, collapsed: false }; } else { cd.groupTotalsFormatter = GroupTotalFormatters.sumTotals; cd.params = { groupFormatterPrefix: 'T: ' /*, groupFormatterSuffix: ' USD'*/ }; cd.grouping = { getter: s.field, formatter: (g) => s.header + `: ${g.value} (${g.count} items)`, aggregators: aggregators, aggregateCollapsed: false, collapsed: false }; } } else { cd.grouping = { getter: s.field, formatter: (g) => s.header + `: ${g.value} (${g.count} items)`, // aggregators: [ // new Aggregators.Sum('ha') // ], aggregateCollapsed: false, collapsed: false }; } } cd = this.getFieldType(cd, s); this.columnDefinitions.push(cd); i++; if (s.visible) { this.columnDefinitionsVisible.push(cd); } }); } else { this.columns = []; } } renderAngularComponent(cellNode: HTMLElement, row: number, dataContext: any, colDef: Column) { if (colDef.params.component && dataContext['hasChanges'] === true) { const componentOutput = this.angularUtilService.createAngularComponent(colDef.params.component); Object.assign(componentOutput.componentRef.instance, { // item: dataContext entityName: this.strTableName, columns: this.columns, columnList: this.logColumnList, rowID: dataContext['id'], }); // use a delay to make sure Angular ran at least a full cycle and make sure it finished rendering the Component setTimeout(() => $(cellNode).empty().html(componentOutput.domElement)); // let themeLink: HTMLLinkElement = document.getElementById(cellNode.id); // setTimeout(() => themeLink = componentOutput.domElement); } } defineGridOption() { const mappedColumnDefinitions = this.columnDefinitionsVisible.map((col) => { return { columnId: col.id.toString(), cssClass: col.cssClass, headerCssClass: col.headerCssClass, width: col.minWidth }; }); this.gridOptions = { presets: { columns: mappedColumnDefinitions }, autoResize: { containerId: 'slick-container-' + this.gridId, sidePadding: 10, bottomPadding: this.slickBottomPadding, minHeight: this.slickMinHeight, maxHeight: this.slickMaxHeight, }, rowHeight: 24, formatterOptions: { dateSeparator: '-' }, enableRowSelection: true, rowSelectionOptions: { // True (Single Selection), False (Multiple Selections) selectActiveRow: true }, autoEdit: true, editable: true, enableCellNavigation: true, enableColumnPicker: true, // enableExcelCopyBuffer: true, editCommandHandler: (item, column, editCommand) => { this._commandQueue.push(editCommand); editCommand.execute(); }, createFooterRow: true, showFooterRow: true, footerRowHeight: 21, // enableDraggableGrouping: true, // createPreHeaderPanel: true, // showPreHeaderPanel: true, // preHeaderPanelHeight: 40, showHeaderRow: true, // !this.defaultHideFilter, enableFiltering: true, enableSorting: true, enableColumnReorder: true, enableExcelExport: false, exportOptions: { sanitizeDataExport: true }, gridMenu: { // iconCssClass: 'fa fa-ellipsis-v', customItems: [ { iconCssClass: 'fa fa-refresh', disabled: false, command: 'refresh', positionOrder: 99, title: 'Refresh', tooltip: 'Refresh List' }, // { // iconCssClass: 'fa fa-retweet', // disabled: false, // command: 'render', // positionOrder: 99, // title: 'Render', // tooltip: 'Render List' // }, { iconCssClass: 'fa fa-plus', disabled: false, command: 'total', positionOrder: 99, title: 'Total', tooltip: 'Total of each column' } ], onCommand: (e, args) => { if (args.command === 'toggle-preheader') { // in addition to the grid menu pre-header toggling (internally), we will also clear grouping // this.clearGrouping(); } else if (args.command === 'refresh') { console.log('refresh args', args); this.emitList(args); } else if (args.command === 'render') { this.render(); } else if (args.command === 'total') { console.log('UpdateAllTotals args', args); this.UpdateAllTotals(args); } }, }, // draggableGrouping: { // dropPlaceHolderText: 'Drop a column header here to group by the column', // // groupIconCssClass: 'fa fa-outdent', // deleteIconCssClass: 'fa fa-times', // onGroupChanged: (e, args) => this.onGroupChanged(args), // onExtensionRegistered: (extension) => this.draggableGroupingPlugin = extension, // } dataItemColumnValueExtractor: function (item, columnDef) { const names = columnDef.field.split('.'); let val = item[names[0]]; for (let i = 1; i < names.length; i++) { if (val && typeof val === 'object' && names[i] in val) { val = val[names[i]]; } else { val = ''; } } return val; } }; if (this.colHeader && this.colHeader.length > 0) { this.gridOptions.createPreHeaderPanel = true; this.gridOptions.showPreHeaderPanel = true; this.gridOptions.preHeaderPanelHeight = 40; this.gridOptions.gridMenu.hideTogglePreHeaderCommand = false; } if (this.allowGrouping) { this.gridOptions.enableDraggableGrouping = true; this.gridOptions.createPreHeaderPanel = true; this.gridOptions.showPreHeaderPanel = true; this.gridOptions.preHeaderPanelHeight = 40; this.gridOptions.gridMenu.hideTogglePreHeaderCommand = false; this.gridOptions.draggableGrouping = { dropPlaceHolderText: 'Drop a column header here to group by the column', // groupIconCssClass: 'fa fa-outdent', deleteIconCssClass: 'fa fa-times', onGroupChanged: (e, args) => this.onGroupChanged(args), onExtensionRegistered: (extension) => this.draggableGroupingPlugin = extension, }; } const cb = this.func.find(s => s.funcType === 'checkbox'); console.log('cb'); console.log(cb); if (cb) { console.log('cb yes'); this.gridOptions.enableHeaderButton = true; this.gridOptions.enableHeaderMenu = false; this.gridOptions.headerButton = { onCommand: (e, args) => { console.log(args); const column = args.column; const button = args.button; const command = args.command; // let columnsWithHighlightingById = {}; // if (!columnsWithHighlightingById) { // columnsWithHighlightingById = {}; // } if (command === 'toggle-checkbox') { if (button.cssClass === 'fa fa-square header-checkbox') { // delete columnsWithHighlightingById[column.id]; button.cssClass = 'fa fa-check-square header-checkbox-check'; // button.tooltip = 'Highlight negative numbers.'; this.onSelectAllClick(true); cb.args = true; this.emitOnRowClick(cb, 'onSelectAllClick'); } else { // columnsWithHighlightingById[column.id] = true; button.cssClass = 'fa fa-square header-checkbox'; // button.tooltip = 'Remove highlight.'; this.onSelectAllClick(false); cb.args = false; this.emitOnRowClick(cb, 'onSelectAllClick'); } // this.gridObj.invalidate(); } } }; } const hc = this.func.find(s => s.funcType === 'hasChanges'); if (hc) { this.gridOptions.enableAsyncPostRender = true; // for the Angular PostRenderer, don't forget to enable it this.gridOptions.asyncPostRenderDelay = 0; // also make sure to remove any delay to render it this.gridOptions.params = { angularUtilService: this.angularUtilService // provide the service to all at once (Editor, Filter, AsyncPostRender) }; } const img = this.func.find(s => s.funcType === 'img'); if (img) { this.gridOptions.rowHeight = img.rowHeight; } if (this.allowLazyLoading === true) { this.gridOptions.multiColumnSort = true; this.gridOptions.pagination = { pageSizes: [5, 10, 20, 50, 100, 500, 1000], pageSize: 20, totalItems: 0 }; this.gridOptions.presets = { // // you can also type operator as string, e.g.: operator: 'EQ' // filters: [ // { columnId: 'gender', searchTerms: ['male'], operator: OperatorType.equal }, // ], // sorters: [ // // direction can be written as 'asc' (uppercase or lowercase) and/or use the SortDirection type // { columnId: 'name', direction: 'asc' } // ], pagination: { pageNumber: 1, pageSize: 20 } }; this.gridOptions.backendServiceApi = { service: new GridOdataService(), options: { enableCount: true, // add the count in the OData query, which will return a property named // "odata.count" (v2) or "@odata.count" (v4) version: 4 // defaults to 2, the query string is slightly different between OData 2 and 4 } as OdataOption, preProcess: () => this.slickLazyLoadingPreProcess(), process: (query) => this.getLazyLoadingApiCall(query), postProcess: (response) => { // this.metrics = response.metrics; this.getLazyLoadingCallback(response); } }; } } getLazyLoadingApiCall(query) { console.log('query: ', query); return new Promise((resolve, reject) => { try { this.lazyLoadingApiCallEvent.emit({ query: query }); this.lazyLoadingChangesSubscription = this.lazyLoadingChanges.subscribe(l => { if (l === query) { resolve(''); } }); } catch (error) { console.error(error); this.loading = false; resolve(''); } }); } getLazyLoadingCallback(datas) { const res = (!this.value || this.value === null) ? [] : this.value; const data = { totalRecordCount: res.length, items: res }; this.loading = false; // totalItems property needs to be filled for pagination to work correctly // however we need to force Angular to do a dirty check, doing a clone object will do just that const countPropName = 'totalRecordCount'; // you can use "totalRecordCount" or any name or "odata.count" when "enableCount" is set // if (this.isCountEnabled) { // countPropName = 'odata.count'; // } this.gridOptions.pagination.totalItems = data[countPropName]; // if (this.metrics) { // this.metrics.totalItemCount = data[countPropName]; // } this.gridOptions = Object.assign({}, this.gridOptions); // once pagination totalItems is filled, we can update the dataset this.value = data['items']; // this.odataQuery = data['query']; this.cd.detectChanges(); } slickLazyLoadingPreProcess() { this.loading = true; this.cd.detectChanges(); } onSelectAllClick(event: boolean) { this.value.forEach(v => { v.isSelected = event; }); this.render(); console.log(this.value); } clearGroupsAndSelects() { this.clearGroupingSelects(); this.clearGrouping(); } clearGrouping() { if (this.draggableGroupingPlugin && this.draggableGroupingPlugin.setDroppedGroups) { this.draggableGroupingPlugin.clearDroppedGroups(); } } clearGroupingSelects() { this.selectedGroupingFields.forEach((g, i) => this.selectedGroupingFields[i] = ''); } collapseAllGroups() { this.dataviewObj.collapseAllGroups(); } expandAllGroups() { this.dataviewObj.expandAllGroups(); } exportToExcel() { this.angularGrid.excelExportService.exportToExcel({ filename: 'Export', format: FileType.xlsx }); } exportToCsv(type = 'csv') { this.angularGrid.exportService.exportToFile({ delimiter: (type === 'csv') ? DelimiterType.comma : DelimiterType.tab, filename: 'myExport', format: (type === 'csv') ? FileType.csv : FileType.txt }); } groupByDuration() { this.clearGrouping(); if (this.draggableGroupingPlugin && this.draggableGroupingPlugin.setDroppedGroups) { this.showPreHeader(); this.draggableGroupingPlugin.setDroppedGroups('duration'); this.gridObj.invalidate(); this.gridObj.render(); } } groupByDurationOrderByCount(isOrderingByCount = false) { this.durationOrderByCount = isOrderingByCount; this.clearGrouping(); this.groupByDuration(); } groupByDurationEffortDriven() { this.clearGrouping(); if (this.draggableGroupingPlugin && this.draggableGroupingPlugin.setDroppedGroups) { this.showPreHeader(); this.draggableGroupingPlugin.setDroppedGroups(['duration', 'effortDriven']); this.gridObj.invalidate(); this.gridObj.render(); } } groupByFieldName(fieldName, index) { this.clearGrouping(); if (this.draggableGroupingPlugin && this.draggableGroupingPlugin.setDroppedGroups) { // get the field names from Group By select(s) dropdown, but filter out any empty fields const groupedFields = this.selectedGroupingFields.filter((g) => g !== ''); this.showPreHeader(); this.draggableGroupingPlugin.setDroppedGroups(groupedFields); this.gridObj.invalidate(); this.gridObj.render(); } } onGroupChanged(change: { caller?: string; groupColumns: Grouping[] }) { // the "caller" property might not be in the SlickGrid core lib yet, reference PR https://github.com/6pac/SlickGrid/pull/303 const caller = change && change.caller || []; const groups = change && change.groupColumns || []; if (Array.isArray(this.selectedGroupingFields) && Array.isArray(groups) && groups.length > 0) { // update all Group By select dropdown this.selectedGroupingFields.forEach((g, i) => this.selectedGroupingFields[i] = groups[i] && groups[i].getter || ''); } else if (groups.length === 0 && caller === 'remove-group') { this.clearGroupingSelects(); } } showPreHeader() { this.gridObj.setPreHeaderPanelVisibility(true); } selectTrackByFn(index, item) { return index; } toggleDraggableGroupingRow() { this.clearGrouping(); this.gridObj.setPreHeaderPanelVisibility(!this.gridObj.getOptions().showPreHeaderPanel); } // Angular-Slickgrid end ngOnDestroy() { if (this.lazyLoadingChangesSubscription !== undefined) { this.lazyLoadingChangesSubscription.unsubscribe(); } } objectIsNull(object: any): boolean { if (!object || object === null) { return true; } else { return false; } } arrayOfObjectIsNull(object: any[]): boolean { if (!object || object === null || !Array.isArray(object) || object.length === 0) { return true; } else { return false; } } stringIsNull(object: string): boolean { if (!object || object === null || object.trim() === '') { return true; } else { return false; } } } @NgModule({ imports: [CommonModule, ButtonModule, TableModule, OverlayPanelModule, CheckboxModule, InputTextModule, FormsModule, AuditTrailListModule, DropdownModule, MultiSelectModule, CurrencyMaskModule, BlockUIModule, PanelModule, ProgressSpinnerModule, ListboxModule, AngularSlickgridModule .forRoot({ // add any Global Grid Options/Config you might want // to avoid passing the same options over and over in each grids of your App // enableAutoResize: true, // autoResize: { // containerId: 'slick-container', // sidePadding: 15 // } }) ], entryComponents: [AuditTrailListComponent], exports: [EtableComponent], declarations: [EtableComponent] }) export class ETableModule { }