flx-ui-datatable
Version:
## AUTHOR Felix Kakra Acheampong from (`Orcons Systems`) Ghana
700 lines • 157 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
import * as tslib_1 from "tslib";
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Validators, FormBuilder } from '@angular/forms';
import { FlxUiDatatableService } from './flx-ui-datatable.service';
import { BehaviorSubject } from 'rxjs';
var FlxUiDatatableComponent = /** @class */ (function () {
function FlxUiDatatableComponent(__form, service) {
this.__form = __form;
this.service = service;
this.classes = {};
this.headers = [];
this.lazyloadingConfig = {};
this.embedPictures = {};
this.dataKeys = [];
this.enableDataExports = false;
this.dataExportsConfig = {};
this.searchKeys = [];
this.dataSrcKey = '';
this.hasActionButtons = false;
this.hideNumbers = false;
this.enableMultipleSelection = false;
this.multipleSelectKey = '';
this.hasAddButton = false;
this.dataUrl = '';
this.actionButtonStart = false;
this.multipleSelectButton = { text: 'Selected', icon: '' };
this.searchPlaceholder = 'Enter name to search';
this.actionHeader = 'Actions';
this.limit = 20;
this.spinnerSrc = '';
this.actionButtons = [];
this.paginationButtons = { background: '#dddddd', textColor: '#335599' };
this.tableHeader = { background: '#ffffff', textColor: '#335599' };
this.searchButton = { background: '#cccccc', textColor: '#335599' };
this.addButton = {};
this.searchBar = { borderSize: '1px', borderColor: '#ccc', background: '#ffffff', textColor: '#000000' };
this.actionButtonsConfig = { position: 'right', beforeNumbers: true };
this.firstActionButtonClicked = new EventEmitter();
this.secondActionButtonClicked = new EventEmitter();
this.thirdActionButtonClicked = new EventEmitter();
this.multipleSelectClicked = new EventEmitter();
this.addButtonClicked = new EventEmitter();
/**
* 18/12/2018
*/
this.textSubstring = {};
this.conditionManipulator = {};
this.isExportAll = false;
this.tData = [];
this.behavior = new BehaviorSubject([]);
this.searchDataTempOffset = [];
this.displayData = this.behavior.asObservable();
this.offset = 1;
this.searchResultFound = [];
}
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.reload = /**
* @return {?}
*/
function () {
this.service.loadFlxDataTableData(this.reloadUrl, true);
};
/**
*
* @param checked Export all selection
*/
/**
*
* @param {?} checked Export all selection
* @return {?}
*/
FlxUiDatatableComponent.prototype.checkToExportOption = /**
*
* @param {?} checked Export all selection
* @return {?}
*/
function (checked) {
this.isExportAll = checked;
};
/**
*
* @param exportType Export type: print|pdf|excel|word
*/
/**
*
* @param {?} exportType Export type: print|pdf|excel|word
* @return {?}
*/
FlxUiDatatableComponent.prototype.exportDocumentsAs = /**
*
* @param {?} exportType Export type: print|pdf|excel|word
* @return {?}
*/
function (exportType) {
var _this = this;
var /** @type {?} */ loading = /** @type {?} */ (document.getElementById("export_loading"));
loading.style.display = 'block';
var /** @type {?} */ headers = (!this.dataExportsConfig.dataColumns || this.dataExportsConfig.dataColumns.length < 1) ? this.dataKeys : this.dataExportsConfig.dataColumns;
var /** @type {?} */ dataToExport = (!this.isExportAll) ? this.displayData : this.service.flxData;
//Subscribe to data
dataToExport.subscribe(function (data) {
var /** @type {?} */ arrayObj = [];
try {
//Loop and push data
for (var data_1 = tslib_1.__values(data), data_1_1 = data_1.next(); !data_1_1.done; data_1_1 = data_1.next()) {
var d = data_1_1.value;
var /** @type {?} */ obj = {};
for (var /** @type {?} */ h = 0; h < headers.length; h++) {
obj[headers[h]] = d[headers[h]];
}
arrayObj.push(obj);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (data_1_1 && !data_1_1.done && (_a = data_1.return)) _a.call(data_1);
}
finally { if (e_1) throw e_1.error; }
}
if (exportType == 'print') {
try {
printJS({ printable: arrayObj, properties: headers, type: 'json' });
loading.style.display = 'none';
}
catch (/** @type {?} */ e) {
loading.style.display = 'none';
// console.log('PrintJS not found. Add `https://printjs-4de6.kxcdn.com/print.min.js` to your index.html or add as part of angular.json script') ;
}
}
else {
var /** @type {?} */ extension_1 = (exportType == 'pdf') ? 'pdf' : (exportType == 'excel') ? 'xlsx' : 'docx';
var /** @type {?} */ pageId = (exportType == 'pdf') ? 3 : (exportType == 'excel') ? 5 : 4;
var /** @type {?} */ requestData = { "data": JSON.stringify(arrayObj) };
_this.service.postData('http://exporter.azurewebsites.net/api/export/ExportFromJSON/', pageId, requestData).subscribe(function (resp) {
var /** @type {?} */ download = 'http://exporter.azurewebsites.net/api/export/GetFile/' + resp;
download += "?fileName=andrei&extension=" + extension_1;
window.location.href = download;
loading.style.display = 'none';
}, (function (e) {
//console.log('file export error',e) ;
}));
}
var e_1, _a;
}).unsubscribe();
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.hasImageEmbeded = /**
* @return {?}
*/
function () {
return this.embedPictures.hasOwnProperty("index");
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.getImage = /**
* @return {?}
*/
function () {
console.log('eoeoe');
// let img = new Image() ;
// img.src = imageSrc ;
// img.onload = ((e)=>{
// return imageSrc ;
// }) ;
// img.onerror = ((e)=>{
// return this.embedPictures.fallbackUrl ;
// })
};
/**
* @param {?} JSONData
* @param {?} ReportTitle
* @param {?} ShowLabel
* @return {?}
*/
FlxUiDatatableComponent.prototype.JSONToCSVConvertor = /**
* @param {?} JSONData
* @param {?} ReportTitle
* @param {?} ShowLabel
* @return {?}
*/
function (JSONData, ReportTitle, ShowLabel) {
//If JSONData is not an object then JSON.parse will parse the JSON string in an Object
var /** @type {?} */ arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
var /** @type {?} */ CSV = '';
//Set Report title in first row or line
CSV += ReportTitle + '\r\n\n';
//This condition will generate the Label/Header
if (ShowLabel) {
var /** @type {?} */ row = "";
//This loop will extract the label from 1st index of on array
for (var /** @type {?} */ index in arrData[0]) {
//Now convert each value to string and comma-seprated
row += index + ',';
}
row = row.slice(0, -1);
//append Label row with line break
CSV += row + '\r\n';
}
//1st loop is to extract each row
for (var /** @type {?} */ i = 0; i < arrData.length; i++) {
var /** @type {?} */ row = "";
//2nd loop will extract each column and convert it in string comma-seprated
for (var /** @type {?} */ index in arrData[i]) {
row += '"' + arrData[i][index] + '",';
}
row.slice(0, row.length - 1);
//add a line break after each row
CSV += row + '\r\n';
}
if (CSV == '') {
alert("Invalid data");
return;
}
//Generate a file name
var /** @type {?} */ fileName = "MyReport_";
//this will remove the blank-spaces from the title and replace it with an underscore
fileName += ReportTitle.replace(/ /g, "_");
//Initialize file format you want csv or xls
var /** @type {?} */ uri = 'data:text/csv;charset=utf-8,' + escape(CSV);
// Now the little tricky part.
// you can use either>> window.open(uri);
// but this will not work in some browsers
// or you will not get the correct file extension
//this trick will generate a temp <a /> tag
var /** @type {?} */ link = document.createElement("a");
link.href = uri;
//set the visibility hidden so it will not effect on your web-layout
link.style = "visibility:hidden";
link.download = fileName + ".csv";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
/**
*
* @param newData
*/
/**
*
* @param {?} newData
* @return {?}
*/
FlxUiDatatableComponent.prototype.changeDisplayData = /**
*
* @param {?} newData
* @return {?}
*/
function (newData) {
this.behavior.next(newData);
this.setColumnWidths();
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
$(window).resize(function () {
/* Same as before */
}).resize();
if (this.isLazyloadingEnabled()) {
this.reloadUrl = this.dataUrl + '&' + this.lazyloadingConfig.apiOffsetKey + '=0&' + this.lazyloadingConfig.apiSearchKey + '=';
}
else {
this.reloadUrl = this.dataUrl;
}
this.searchForm = this.__form.group({
searchString: ['', Validators.required]
});
this.searchForm = this.__form.group({
searchString: ['', Validators.required]
});
this.service.limit = this.limit;
this.service.setLazyloadingConfig(this.lazyloadingConfig);
this.service.setDataUrl(this.dataUrl);
this.service.setDataSrcKey(this.dataSrcKey);
var /** @type {?} */ url = (this.isLazyloadingEnabled()) ? this.dataUrl + '&' + this.lazyloadingConfig.apiOffsetKey + '=0&' + this.lazyloadingConfig.apiSearchKey + '=' : this.dataUrl;
this.service.loadFlxDataTableData(url);
this.service.flxData.subscribe(function (resp) {
_this.tData = resp;
var /** @type {?} */ obj = [];
if (_this.tData.length > _this.limit) {
for (var /** @type {?} */ i = 0; i < _this.limit; i++) {
obj.push(_this.tData[i]);
}
// this.service.dataOffset = this.limit;
}
else {
var /** @type {?} */ counter = 0;
for (var /** @type {?} */ i = 0; i < _this.tData.length; i++) {
obj.push(_this.tData[i]);
counter++;
}
// this.service.dataOffset = obj.length;
}
_this.searchDataTempOffset = obj;
_this.changeDisplayData(obj);
});
};
/**
* @param {?} values
* @param {?} form
* @return {?}
*/
FlxUiDatatableComponent.prototype.searchDataInApi = /**
* @param {?} values
* @param {?} form
* @return {?}
*/
function (values, form) {
this.service.chageDataTable([]);
this.service.loadFlxDataTableData(this.dataUrl + '&' + this.lazyloadingConfig.apiOffsetKey + '=0&' + this.lazyloadingConfig.apiSearchKey + '=' + values.searchString);
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
var /** @type {?} */ eachColumnWidth = this.returColumnswidth();
$(window).ready(function () {
$(".flx-table-thead tr th").css({ 'width': eachColumnWidth + '%' });
});
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.setColumnWidths = /**
* @return {?}
*/
function () {
var /** @type {?} */ eachColumnWidth = this.returColumnswidth();
$(window).ready(function () {
$(".flx-table-data tbody tr td").css({ 'width': eachColumnWidth + '%' });
});
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.returColumnswidth = /**
* @return {?}
*/
function () {
var /** @type {?} */ hasNumbers = (!this.hideNumbers) ? 0 : 1;
var /** @type {?} */ hasActionButtons = (!this.hasActionButtons) ? 0 : 1;
var /** @type {?} */ numberOfColumns = (this.headers.length + 1) + hasActionButtons + hasNumbers;
console.log('number_of_columns', numberOfColumns);
var /** @type {?} */ eachColumnWidth = 100 / numberOfColumns;
return eachColumnWidth;
};
/**
* @param {?} index
* @param {?} buttonIndex
* @return {?}
*/
FlxUiDatatableComponent.prototype.actionButtonClicked = /**
* @param {?} index
* @param {?} buttonIndex
* @return {?}
*/
function (index, buttonIndex) {
var _this = this;
this.displayData.subscribe(function (data) {
if (buttonIndex == 0) {
return _this.firstActionButtonClicked.emit({ index: index, data: data[index] });
}
else if (buttonIndex == 1) {
return _this.secondActionButtonClicked.emit({ index: index, data: data[index] });
}
else {
_this.thirdActionButtonClicked.emit({ index: index, data: data[index] });
}
}).unsubscribe();
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.addButtonClick = /**
* @return {?}
*/
function () {
this.addButtonClicked.emit();
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.confirmDelete = /**
* @return {?}
*/
function () {
return this.multipleSelectClicked.emit(this.service.multipleDeletion);
};
/**
* @param {?} checked
* @return {?}
*/
FlxUiDatatableComponent.prototype.addRemove = /**
* @param {?} checked
* @return {?}
*/
function (checked) {
var _this = this;
if (checked) {
this.displayData.subscribe(function (data) {
var /** @type {?} */ counter = 0;
try {
for (var data_2 = tslib_1.__values(data), data_2_1 = data_2.next(); !data_2_1.done; data_2_1 = data_2.next()) {
var i = data_2_1.value;
try {
_this.service.multipleDeletion.push(i[_this.multipleSelectKey]);
}
catch (/** @type {?} */ e) { }
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (data_2_1 && !data_2_1.done && (_a = data_2.return)) _a.call(data_2);
}
finally { if (e_2) throw e_2.error; }
}
// console.log(this.service.multipleDeletion) ;
var e_2, _a;
}).unsubscribe();
}
else {
this.service.multipleDeletion = [];
}
};
/**
* @param {?} dataKeyvalue
* @param {?} index
* @param {?} selected
* @return {?}
*/
FlxUiDatatableComponent.prototype.addRemoveDeleteItem = /**
* @param {?} dataKeyvalue
* @param {?} index
* @param {?} selected
* @return {?}
*/
function (dataKeyvalue, index, selected) {
var _this = this;
if (!selected) {
for (var /** @type {?} */ i = 0; i < this.service.multipleDeletion.length; i++) {
if (dataKeyvalue == this.service.multipleDeletion[i]) {
this.service.multipleDeletion.splice(i, 1);
break;
}
}
}
else {
this.displayData.subscribe(function (resp) {
_this.service.multipleDeletion.push(resp[index][_this.multipleSelectKey]);
}).unsubscribe();
}
// console.log('left '+dataKeyvalue,this.service.multipleDeletion) ;
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.getSearchColumns = /**
* @return {?}
*/
function () {
return (this.hasAddButton) ? (this.enableDataExports) ? 'col-md-6 search-container' : 'col-md-7 search-container' :
(this.enableDataExports) ? 'col-md-7 search-container' : 'col-md-8 search-container';
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.disablePrevtButton = /**
* @return {?}
*/
function () {
return Math.ceil(this.service.dataOffset / this.limit) <= 1;
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.disableNextButton = /**
* @return {?}
*/
function () {
return Math.ceil(this.service.dataOffset / this.limit) == Math.ceil(this.service.totalItems / this.limit);
};
/**
* @return {?}
*/
FlxUiDatatableComponent.prototype.isLazyloadingEnabled = /**
* @return {?}
*/
function () {
return this.lazyloadingConfig.hasOwnProperty("apiOffsetKey") && this.lazyloadingConfig.apiOffsetKey;
};
/**
* @param {?} type
* @return {?}
*/
FlxUiDatatableComponent.prototype.nextPrevItem = /**
* @param {?} type
* @return {?}
*/
function (type) {
var _this = this;
if (this.isLazyloadingEnabled()) {
this.service.loadFinish = false;
this.service.getDataLength().then(function (dataLength) {
_this.service.chageDataTable([]);
_this.service.dataOffset = (type == 'prev') ? ((_this.service.dataOffset - _this.limit) - _this.limit) : _this.service.dataOffset;
var /** @type {?} */ url = (_this.isLazyloadingEnabled()) ? _this.dataUrl + '&' + _this.lazyloadingConfig.apiOffsetKey + '=' + _this.service.dataOffset + '&' + _this.lazyloadingConfig.apiSearchKey + '=' : _this.dataUrl;
_this.service.loadFlxDataTableData(url);
}).catch(function (e) {
//console.log('error',e) ;
});
return;
}
// Paginate if lazyloading is disabled
if (type == 'prev') {
this.paginateDatatableRecord((this.service.dataOffset - this.limit) - this.limit);
}
else {
if (this.service.dataOffset < this.limit) {
this.paginateDatatableRecord(this.service.dataOffset + (this.limit - 1));
}
else {
this.paginateDatatableRecord(this.service.dataOffset);
}
}
};
/**
* @param {?=} searchString
* @return {?}
*/
FlxUiDatatableComponent.prototype.filterData = /**
* @param {?=} searchString
* @return {?}
*/
function (searchString) {
var _this = this;
if (searchString === void 0) { searchString = ''; }
if (searchString == '') {
this.isSearching = false;
}
else {
this.isSearching = true;
}
this.changeDisplayData([]);
this.service.flxData.subscribe(function (data) {
var /** @type {?} */ searchResults = [];
//If no string provided. Register all the previous data to the dataset
if (searchString.trim() == '') {
_this.changeDisplayData(_this.searchDataTempOffset);
return;
}
//Check if searchKeys are set else use dataKeys as searchKeys
var /** @type {?} */ searchKeys = (_this.searchKeys.length < 1) ? _this.dataKeys : _this.searchKeys;
for (var /** @type {?} */ i = 0; i < data.length; i++) {
//Variable to check if data is found
var /** @type {?} */ found = -1;
for (var /** @type {?} */ x = 0; x < searchKeys.length; x++) {
try {
if (data[i][String(searchKeys[x])].toLowerCase().indexOf(searchString.toLocaleLowerCase()) !== -1) {
found = i;
break;
}
}
catch (/** @type {?} */ e) { }
}
//If found push the index of the data to the searchResults variable
if (found > -1) {
searchResults.push(data[found]);
}
}
_this.searchResultFound = searchResults;
//Register the results to the dataset
//Register the results to the dataset
_this.changeDisplayData(searchResults);
_this.setColumnWidths();
}).unsubscribe();
};
/**
* @param value offset value
*/
/**
* @param {?} value offset value
* @return {?}
*/
FlxUiDatatableComponent.prototype.paginateDatatable = /**
* @param {?} value offset value
* @return {?}
*/
function (value) {
var _this = this;
// Check if lazy loading is enabled
if (this.isLazyloadingEnabled()) {
this.service.loadFinish = false;
// Subscribe to get the data length
this.service.getDataLength().then(function () {
_this.service.chageDataTable([]);
// Check if all is selected to prevent NAN value
if (value != 'all') {
_this.service.dataOffset = parseInt(value);
}
// setup url
var /** @type {?} */ url = (_this.isLazyloadingEnabled()) ? _this.dataUrl + '&' + _this.lazyloadingConfig['apiOffsetKey'] + '=' + value + '&' + _this.lazyloadingConfig.apiSearchKey + '=' : _this.dataUrl;
// paginate
// paginate
_this.service.loadFlxDataTableData(url, false);
}).catch(function (e) {
// console.log('error',e) ;
});
return;
}
this.paginateDatatableRecord(value);
};
/**
*
* @param value pagination number
* Perform pagination to the dataset
* @return
*/
/**
*
* @param {?} value pagination number
* Perform pagination to the dataset
* @return {?}
*/
FlxUiDatatableComponent.prototype.paginateDatatableRecord = /**
*
* @param {?} value pagination number
* Perform pagination to the dataset
* @return {?}
*/
function (value) {
var _this = this;
if (this.lazyloadingConfig.hasOwnProperty("apiOffsetKey") && this.lazyloadingConfig['apiOffsetKey']) {
this.service.loadFinish = false;
this.service.getDataLength().then(function (dataLength) {
_this.service.chageDataTable([]);
_this.service.dataOffset = parseInt(value) + _this.limit;
_this.service.loadFlxDataTableData(_this.dataUrl + '&' + _this.lazyloadingConfig.apiOffsetKey + '=' + value + '&' + _this.lazyloadingConfig.apiSearchKey + '=');
_this.setColumnWidths();
}).catch(function (e) {
// console.log('error',e) ;
});
return;
}
var /** @type {?} */ num = parseInt(value);
if (num <= 0) {
this.offset = 1;
this.service.dataOffset = this.limit;
}
else {
if (value != 'all') {
this.offset = num + 1;
this.service.dataOffset = num + this.limit;
}
else {
this.offset = 1;
}
}
this.service.flxData.subscribe(function (data) {
if (value !== 'all') {
var /** @type {?} */ paginateResult = [];
for (var /** @type {?} */ i = value; i < (_this.limit + parseInt(value)); i++) {
if (data[i]) {
paginateResult.push(data[i]);
}
}
if (paginateResult.length > 0) {
_this.changeDisplayData(paginateResult);
}
}
else {
_this.changeDisplayData(data);
_this.searchDataTempOffset = data;
}
_this.setColumnWidths();
}).unsubscribe();
};
FlxUiDatatableComponent.decorators = [
{ type: Component, args: [{
selector: 'flx-ui-datatable',
template: "<div class=\"col-md-12 flx-ui-datatable-main {{ classes?.maincontainer }}\">\n <div id=\"export_loading\" class=\"col-md-12 text-center\" style=\"display: none;margin-bottom:0.5em;color:#dddddd;font-size:13px;font-weight:bold;\">Exporting...</div>\n <div class=\"col-md-12 flx-ui-datatable-header\">\n <div class=\"container-fluid\">\n <div class=\"row\">\n <div class=\"col-xs-3 col-sm-3 pagination-select col-md-2\" style=\"position:relative;z-index: 1;\">\n <select class=\"form-control rmsh rmrd {{ classes?.paginationselect }}\" (change)=\"paginateDatatable($event?.target?.value)\">\n <option *ngFor=\"let paging of service?.pagination\" [value]=\"paging?.value\">{{ paging?.label }}</option>\n </select>\n </div>\n <div class=\"col-xs-5 col-sm-5 col-md-2 text-center flx-datatable-pagination rmpd\" style=\"position:relative;z-index: 2;\">\n <button mat-icon-button [ngClass]=\"{'flx-pagination-end': disablePrevtButton()}\" (click)=\"nextPrevItem('prev')\" [disabled]=\"disablePrevtButton()\" class=\"flx-ui-datatable-pagination-buttons {{ classes?.paginationButton }}\"><span class=\"fa fa-angle-double-left fa-1x\"></span> <span class=\"flx-datatable-tooltip-prev\" [ngClass]=\"{'flx-pagination-end': disablePrevtButton()}\">Previous</span> </button>\n <span *ngIf=\"!isSearching;else searching\">{{ service?.dataOffset | ceil: limit }} / {{ service?.totalItems | ceil: limit }}</span>\n <ng-template #searching>\n \n </ng-template>\n <button mat-icon-button [ngClass]=\"{'flx-pagination-end': disableNextButton()}\" (click)=\"nextPrevItem('next')\" [disabled]=\"disableNextButton()\" class=\"flx-ui-datatable-pagination-buttons {{ classes?.paginationButton }}\"><span class=\"fa fa-angle-double-right fa-1x\"></span> <span class=\"flx-datatable-tooltip-next\" [ngClass]=\"{'flx-pagination-end': disableNextButton()}\">Next</span></button>\n </div>\n <div [class]=\"'search-bar '+getSearchColumns()\">\n <input type=\"text\" *ngIf=\"!isLazyloadingEnabled()\" [style.background]=\"searchBar?.background\" [style.color]=\"searchBar?.textColor\" [ngStyle]=\"{border:searchBar?.borderSize +' solid '+ searchBar?.borderColor} \" (keyup)=\"filterData($event?.target?.value)\" class=\"form-control rmsh rmrd customclass\" [placeholder]=\"searchPlaceholder\">\n <form (ngSubmit)=\"searchDataInApi(srch?.value,srch)\" #srch=\"ngForm\" *ngIf=\"isLazyloadingEnabled()\">\n <div class=\"input-group\">\n <input type=\"text\" required name=\"searchString\" ngModel [style.background]=\"searchBar?.background\" [style.color]=\"searchBar?.textColor\" [ngStyle]=\"{border:searchBar?.borderSize +' solid '+ searchBar?.borderColor} \" class=\"form-control rmsh rmrd {{ classes?.searchbar }}\" [placeholder]=\"searchPlaceholder\">\n <span class=\"input-group-addon\">\n <button [disabled]=\"!srch?.valid\" type=\"submit\" class=\"btn btn-default btn-clear btn-md\">\n <i class=\"fa fa-search\"></i>\n </button>\n </span>\n </div>\n </form>\n </div>\n <div class=\"col-md-1 text-right rmpd\" *ngIf=\"hasAddButton\">\n <button (click)=\"addButtonClick()\" class=\"{{ classes?.addButton }}\" [style.background]=\"addButton?.background\" [style.borderColor]=\"addButton?.background\" [style.color]=\"addButton?.textColor\"><span class=\"fa fa-plus\"></span> Add</button>\n </div>\n <div class=\"col-md-1 text-right rmpd export-cnt\" *ngIf=\"enableDataExports\">\n <div class=\"dropdown\">\n <button class=\"btn btn-default {{ classes?.exportButton }} dropdown-toggle\" type=\"button\" data-toggle=\"dropdown\">\n <i class=\"fa fa-angle-down\"></i>\n </button>\n <ul class=\"dropdown-menu dropdown-menu-export {{ classes?.exportDropdown }}\">\n <li class=\"dropdown-header\">{{ dataExportsConfig?.title }}. <input type=\"checkbox\" (change)=\"checkToExportOption($event?.target?.checked)\" style=\"position: relative;top:0.3em;\"> <sup style=\"font-size:10px;color:#999;\"> All</sup></li> \n <li class=\"divider\"></li>\n <li class=\"dropdown-submenu\" *ngFor=\"let export of dataExportsConfig?.exportsTo\" (click)=\"exportDocumentsAs(export)\">\n <a href=\"javascript:void(0)\" class=\"btn btn-default btn-sm form-control\" *ngIf=\"export=='print'\"><i class=\"glyphicon glyphicon-print\"></i> Print</a>\n <a href=\"javascript:void(0)\" class=\"btn btn-default btn-sm form-control\" *ngIf=\"export=='pdf'\" style=\"color:#ff0000\"><i class=\"glyphicon glyphicon-file\"></i> PDF</a>\n <a href=\"javascript:void(0)\" class=\"btn btn-default btn-sm form-control\" *ngIf=\"export=='excel'\" style=\"color:#009900;\"><i class=\"glyphicon glyphicon-file\"></i> Excel</a> \n <a href=\"javascript:void(0)\" class=\"btn btn-default btn-sm form-control\" *ngIf=\"export=='word'\" style=\"color:#335599;\"><i class=\"glyphicon glyphicon-file\"></i> Word</a> \n </li>\n <li class=\"divider\"></li>\n <li class=\"dropdown-header\">\n <span *ngIf=\"!isExportAll\">{{ (displayData | async)?.length }}</span>\n <span *ngIf=\"isExportAll\">{{ (service?.flxData | async)?.length }}</span> \n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"container-fluid\">\n <div class=\"row\">\n <div class=\"col-md-12 rmpd table-responsive flx-tabl-container\">\n <table class=\"table {{ classes?.tableType }} th-table\">\n <thead class=\"{{ classes?.tableHeader }} flx-table-thead\">\n <tr>\n <!-- Actions buttons header left before numbers -->\n <th *ngIf=\"hasActionButtons && (actionButtonsConfig?.position=='left' && actionButtonsConfig?.beforeNumbers)\">{{ actionHeader }} \n <input type=\"checkbox\" [checked]=\"service?.multipleDeletion?.length>0\" (change)=\"addRemove($event?.target?.checked)\" *ngIf=\"enableMultipleSelection\">\n <button class=\"btn btn-danger btn-xs flx-multiple-deletion-button\" *ngIf=\"enableMultipleSelection && service?.multipleDeletion?.length>0\" (click)=\"confirmDelete()\"><span [class]=\"multipleSelectButton?.icon\"></span> {{ multipleSelectButton?.text }}</button>\n </th>\n\n\n <th *ngIf=\"!hideNumbers\">N<sup><u>o</u></sup></th>\n\n <!-- Actions buttons header left after numbers -->\n <th *ngIf=\"hasActionButtons && (actionButtonsConfig?.position=='left' && !actionButtonsConfig?.beforeNumbers)\">{{ actionHeader }} \n <input type=\"checkbox\" [checked]=\"service?.multipleDeletion?.length>0\" (change)=\"addRemove($event?.target?.checked)\" *ngIf=\"enableMultipleSelection\">\n <button class=\"btn btn-danger btn-xs flx-multiple-deletion-button\" *ngIf=\"enableMultipleSelection && service?.multipleDeletion?.length>0\" (click)=\"confirmDelete()\"><span [class]=\"multipleSelectButton?.icon\"></span> {{ multipleSelectButton?.text }}</button>\n </th>\n\n\n <th *ngFor=\"let header of headers\">{{ header }}</th>\n\n <!-- Actions buttons header right -->\n <th *ngIf=\"hasActionButtons && (actionButtonsConfig?.position=='right')\">{{ actionHeader }} \n <input type=\"checkbox\" [checked]=\"service?.multipleDeletion?.length>0\" (change)=\"addRemove($event?.target?.checked)\" *ngIf=\"enableMultipleSelection\">\n <button class=\"btn btn-danger btn-xs flx-multiple-deletion-button\" *ngIf=\"enableMultipleSelection && service?.multipleDeletion?.length>0\" (click)=\"confirmDelete()\"><span [class]=\"multipleSelectButton?.icon\"></span> {{ multipleSelectButton?.text }}</button>\n </th>\n </tr>\n </thead>\n </table>\n <perfect-scrollbar class=\"data-scroll-content {{ classes?.dataScrollContent }}\">\n <table class=\"table {{ classes?.tableType }} flx-table-data\"> \n <tbody class=\"flxdatatablebodyscrollbar\">\n <tr *ngIf=\"!service?.loadFinish\"> \n <td colspan=\"20\" class=\"text-center\">\n <img *ngIf=\"spinnerSrc\" [class]=\"classes?.spinner\" [src]=\"spinnerSrc\" style=\"margin-top:1em;margin-bottom:1em;\">\n </td>\n </tr>\n <tr class=\"flxuidatatablerow\" id=\"flxdatatable_singlerow\" *ngFor=\"let data of displayData | async;let i=index\">\n \n <!-- Buttons Left Before Numbers -->\n <td class=\"table-buttons\" *ngIf=\"hasActionButtons && (actionButtonsConfig?.position=='left' && actionButtonsConfig?.beforeNumbers)\" scope=\"row\">\n <span *ngFor=\"let aButton of actionButtons;let buttonIndex=index\">\n <button type=\"button\" (click)=\"actionButtonClicked(i,buttonIndex)\" class=\"btn {{ aButton?.class }}\">\n <div class=\"toltip\" class=\"flx-tooltip\" [ngClass]=\"{'flx-tooltip-left':aButton?.tooltipPosition=='left','flx-tooltip-bottom':aButton?.tooltipPosition=='bottom','flx-tooltip-right':aButton?.tooltipPosition=='right'}\" *ngIf=\"aButton?.tooltip\">{{ aButton?.tooltip }}</div>\n <span class=\"action-button-icon-left\" [class]=\"aButton?.icon\" *ngIf=\"!aButton?.iconPosition || aButton?.iconPosition!='right'\"></span>\n <span class=\"button-text\"> {{ aButton?.text }} </span>\n <span [class]=\"aButton?.icon\" *ngIf=\"aButton?.iconPosition=='right'\"></span>\n </button>\n </span> \n <input type=\"checkbox\" checked (change)=\"addRemoveDeleteItem(data[multipleSelectKey],i,$event?.target?.checked)\" *ngIf=\"enableMultipleSelection && service?.multipleDeletion?.length>0\">\n </td>\n \n <!-- Numbers -->\n <td class=\"{{ classes?.tableData }}\" *ngIf=\"!hideNumbers\" style=\"color: #999;\">{{ offset+i }}</td>\n \n <!-- Buttons Left After Numbers -->\n <td class=\"table-buttons\" *ngIf=\"hasActionButtons && (actionButtonsConfig?.position=='left' && !actionButtonsConfig?.beforeNumbers)\" scope=\"row\">\n <span *ngFor=\"let aButton of actionButtons;let buttonIndex=index\">\n <button type=\"button\" (click)=\"actionButtonClicked(i,buttonIndex)\" class=\"btn {{ aButton?.class }}\">\n <div class=\"toltip\" class=\"flx-tooltip\" [ngClass]=\"{'flx-tooltip-left':aButton?.tooltipPosition=='left','flx-tooltip-bottom':aButton?.tooltipPosition=='bottom','flx-tooltip-right':aButton?.tooltipPosition=='right'}\" *ngIf=\"aButton?.tooltip\">{{ aButton?.tooltip }}</div>\n <span class=\"action-button-icon-left\" [class]=\"aButton?.icon\" *ngIf=\"!aButton?.iconPosition || aButton?.iconPosition!='right'\"></span>\n <span class=\"button-text\"> {{ aButton?.text }} </span>\n <span [class]=\"aButton?.icon\" *ngIf=\"aButton?.iconPosition=='right'\"></span>\n </button>\n </span> \n <input type=\"checkbox\" checked (change)=\"addRemoveDeleteItem(data[multipleSelectKey],i,$event?.target?.checked)\" *ngIf=\"enableMultipleSelection && service?.multipleDeletion?.length>0\">\n </td>\n \n <!-- Main -->\n <td class=\"{{ classes?.tableData }}\" *ngFor=\"let dataKey of dataKeys;let x=index\">\n <img *ngIf=\"hasImageEmbeded() && x==embedPictures?.index; else nopicture\" [class]=\"'img-fall-back ' +embedPictures?.class\" [src]=\"embedPictures?.rootFolder+data[dataKey]\" [flx-ui-datatable-img-fallback]=\"embedPictures?.fallbackUrl\" >\n <ng-template #nopicture>\n <section *ngIf=\"textSubstring?.atIndexes && (textSubstring?.atIndexes | haslimittext:x);else nolimittext\">\n {{ textSubstring | limittext: data[dataKey] }}\n </section>\n <ng-template #nolimittext>\n <span>{{ data[dataKey] }}</span>\n </ng-template>\n </ng-template> \n </td>\n <!-- Buttons -->\n <td class=\"table-buttons\" *ngIf=\"hasActionButtons && actionButtonsConfig?.position!='left'\">\n <span *ngFor=\"let aButton of actionButtons;let buttonIndex=index\">\n <button type=\"button\" (click)=\"actionButtonClicked(i,buttonIndex)\" class=\"btn {{ aButton?.class }}\">\n <div class=\"toltip\" class=\"flx-tooltip\" [ngClass]=\"{'flx-tooltip-left':aButton?.tooltipPosition=='left','flx-tooltip-bottom':aButton?.tooltipPosition=='bottom','flx-tooltip-right':aButton?.tooltipPosition=='right'}\" *ngIf=\"aButton?.tooltip\">{{ aButton?.tooltip }}</div>\n <span class=\"action-button-icon-left\" [class]=\"aButton?.icon\" *ngIf=\"!aButton?.iconPosition || aButton?.iconPosition!='right'\"></span>\n <span class=\"button-text\"> {{ aButton?.text }} </span>\n <span [class]=\"aButton?.icon\" *ngIf=\"aButton?.iconPosition=='right'\"></span>\n </button>\n </span> \n <input type=\"checkbox\" checked (change)=\"addRemoveDeleteItem(data[multipleSelectKey],i,$event?.target?.checked)\" *ngIf=\"enableMultipleSelection && service?.multipleDeletion?.length>0\">\n </td>\n </tr>\n <tr *ngIf=\"tData?.length<1\">\n <td colspan=\"10\" class=\"text-center\" *ngIf=\"service?.loadFinish\">\n <span style=\"color:#ff0000;font-size:13px;\">No data found</span> <br>\n <button type=\"button\" style=\"margin-top:1em;\" (click)=\"reload()\" class=\"btn btn-default {{ classes?.reloadbutton }}\" color=\"primary\"><span class=\"fa fa-refresh\"></span> Reload</button>\n </td>\n </tr>\n </tbody>\n </table>\n </perfect-scrollbar>\n <div class=\"row\">\n <div class=\"col-md-12 rmpd flx-total-data\" *ngIf=\"showBottomInfo\">\n <div class=\"row\" *ngIf=\"!isSearching;else bottomInfoSearching\">\n <div class=\"col-md-4 text-left rmpd\">Total pagination: <span> {{ service?.totalItems | ceil: limit }}</span></div>\n <div class=\"col-md-4 text-center rmpd\"># of items per pagination: <span>{{ limit }}</span></div>\n <div class=\"col-md-4 text-right rmpd\">Total items: <span>{{ (service?.flxData | async)?.length }}</span></div>\n </div>\n <ng-template #bottomInfoSearching>\n <div class=\"row\">\n <div class=\"col-md-12 text-right rmpd\">Total search result: <span>{{ searchResultFound?.length }}</span></div>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>",
styles: [".flx-ui-datatable-main{background-color:#fff;padding-top:1em;padding-bottom:1em}.flx-ui-datatable-main .btn-danger{background-color:#f50057;border:1px solid #f50057;box-shadow:0 3px 5px 1px #ddd;-moz-box-shadow:0 3px 5px 1px #ddd;-webkit-box-shadow:0 3px 5px 1px #ddd;-o-box-shadow:0 3px 5px 1px #ddd;-ms-box-shadow:0 3px 5px 1px #ddd;border-radius:3px;margin-left:.3em}.flx-ui-datatable-main #flxdatatablebodyscrollbar,.flx-ui-datatable-main .table-responsive,.flx-ui-datatable-main .table-responsive table{width:100%}.flx-ui-datatable-main img.img-fall-back{width:30px;height:30px}.flx-ui-datatable-main .pagination-select input[type=text],.flx-ui-datatable-main .pagination-select select,.flx-ui-datatable-main .search-bar input[type=text],.flx-ui-datatable-main .search-bar select{border-top:none!important;border-left:none!important;border-right:none!important;border-bottom:2px solid #ddd!important;border-radius:0!important;box-shadow:0 0 0 0 transparent!important;-moz-box-shadow:0 0 0 0 transparent!important;-webkit-box-shadow:0 0 0 0 transparent!important;-o-box-shadow:0 0 0 0 transparent!important;-ms-box-shadow:0 0 0 0 transparent!important}.flx-ui-datatable-main .pagination-select input[type=text]:focus,.flx-ui-datatable-main .pagination-select select:focus,.flx-ui-datatable-main .search-bar input[type=text]:focus,.flx-ui-datatable-main .search-bar select:focus{border-bottom-color:#359!important;transition:.5s;-moz-transition:.5s;-webkit-transition:.5s;-o-transition:.5s;-ms-transition:.5s}.flx-ui-datatable-main .pagination-select select,.flx-ui-datatable-main .search-bar select{-webkit-appearance:none;appearance:none;-moz-appearance:none}.flx-ui-datatable-main .dropdown-toggle::after{display:none}.flx-ui-datatable-main .dropdown-menu-export{margin-left:-130px;padding-left:1em;padding-right:1em;width:100px!important;margin-top:1em;border:1px solid #ddd!important}.flx-ui-datatable-main .dropdown-menu-export::before{content:\"\";width:auto;height:auto;position:absolute;top:-20px;right:3px;border:10px solid;border-color:transparent transparent #ddd}.flx-ui-datatable-main .flx-datatable-pagination{padding-top:.5em}.flx-ui-datatable-main .flx-datatable-pagination button{width:35px!important;height:35px!important;border-radius:50em!important;border:none!important;box-shadow:0 3px 10px 0 #b3c4e6;-moz-box-shadow:0 3px 10px 0 #b3c4e6;-webkit-box-shadow:0 3px 10px 0 #b3c4e6;-o-box-shadow:0 3px 10px 0 #b3c4e6;-ms-box-shadow:0 3px 10px 0 #b3c4e6;background-color:#359;color:#fff;font-size:23px;font-weight:700;position:absolute;top:0}.flx-ui-datatable-main .flx-datatable-pagination button:first-child{left:0}.flx-ui-datatable-main .flx-datatable-pagination button:first-child .flx-datatable-tooltip-prev{position:absolute;left:0;font-size:13px;font-weight:400;color:#fff;background-color:#359;padding-left:.3em;padding-right:.3em;border-radius:3px;margin-left:-57px;margin-top:.3em;box-shadow:0 3px 10px 0 #b3c4e6!important;-moz-box-shadow:0 3px 10px 0 #b3c4e6!important;-webkit-box-shadow:0 3px 10px 0 #b3c4e6!important;-o-box-shadow:0 3px 10px 0 #b3c4e6!important;-ms-box-shadow:0 3px 10px 0 #b3c4e6!important;visibility:hidden}.flx-ui-datatable-main .flx-datatable-pagination button:hover>span.flx-datatable-tooltip-next,.flx-ui-datatable-main .flx-datatable-pagination button:hover>span.flx-datatable-tooltip-prev{visibility:visible}.flx-ui-datatable-main .flx-datatable-pagination .flx-pagination-end{background-color:#f50057!important;box-shadow:0 3px 10px 0 #ffc2d8!important;-moz-box-shadow:0 3px 10px 0 #ffc2d8!important;-webkit-box-shadow:0 3px 10px 0 #ffc2d8!important;-o-box-shadow:0 3px 10px 0 #ffc2d8!important;-ms-box-shadow:0 3px 10px 0 #ffc2d8!important;cursor:not-allowed}.flx-ui-datatable-main .flx-datatable-pagination .flx-pagination-end:hover>span.flx-datatable-tooltip-next,.flx-ui-datatable-main .flx-datatable-pagination .flx-pagination-end:hover>span.flx-datatable-tooltip-prev{visibility:hidden}.flx-ui-datatable-main .flx-datatable-pagination button:last-child{right:0}.flx-ui-datatable-main .flx-datatable-pagination button:last-child .flx-datatable-tooltip-next{position:absolute;left:0;font-size:13px;font-weight:400;color:#fff;background-color:#359;padding-left:.3em;padding-right:.3em;border-radius:3px;margin-left:35px;margin-top:.5em;box-shadow:0 3px 10px 0 #b3c4e6!important;-moz-box-shadow:0 3px 10px 0 #b3c4e6!important;-webkit-box-shadow:0 3px 10px 0 #b3c4e6!important;-o-box-shadow:0 3px 10px 0 #b3c4e6!important;-ms-box-shadow:0 3px 10px 0 #b3c4e6!important;visibility:hidden}.flx-ui-datatable-main .export-cnt button{border-radius:50em!important}.flx-ui-datatable-main .flx-tabl-container table.th-table{margin-top:.5em}.flx-ui-datatable-main table tbody tr{padding-top:0!important}.flx-ui-datatable-main table tbody tr td{padding-top:.5em;border-top:1px solid #f0f0f0;border-bottom:1px solid #f0f0f0}.flx-ui-datatable-main table tbody tr td button{margin-right:.3em;margin-left:0}.flx-ui-datatable-main table tbody tr td button div.flx-tooltip{position:absolute;background-color:rgba(32,27,27,.808);text-align:center;font-size:13px;color:#fff;border-radius:3px;box-shadow:0 3px 20px 0 #4b4949;-moz-box-shadow:0 3px 20px 0 #4b4949;-webkit-box-shadow:0 3px 20px 0 #4b4949;-o-box-shadow:0 3px 20px 0 #4b4949;-ms-box-shadow:0 3px 20px 0 #4b4949;margin-left:-2.5em;margin-top:-2.8em;visibility:hidden;width:80px;padding:.3em .5em}.flx-ui-datatable-main table tbody tr td button .flx-tooltip-left{margin-left:-95px!important;margin-top:-.3em!important}.flx-ui-datatable-main table tbody tr td button .flx-tooltip-bot