import {NgModule,Component,ElementRef,OnInit,AfterContentInit,Input,Output,EventEmitter,ContentChild,ContentChildren,QueryList,TemplateRef,OnChanges,SimpleChanges,ChangeDetectionStrategy,ChangeDetectorRef, ViewEncapsulation} from '@angular/core';
import {CommonModule} from '@angular/common';
import {ObjectUtils} from 'mirra-ui/utils';
import {Header,Footer,PrimeTemplate,SharedModule} from 'mirra-ui/api';
import {PaginatorModule} from 'mirra-ui/paginator';
import {BlockableUI} from 'mirra-ui/api';
import {FilterUtils} from 'mirra-ui/utils';
@Component({
selector: 'p-dataView',
template: `
`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
styleUrls: ['./dataview.scss']
})
export class DataView implements OnInit,AfterContentInit,BlockableUI,OnChanges {
@Input() layout: string = 'list';
@Input() paginator: boolean;
@Input() rows: number;
@Input() totalRecords: number;
@Input() pageLinks: number = 5;
@Input() rowsPerPageOptions: any[];
@Input() paginatorPosition: string = 'bottom';
@Input() alwaysShowPaginator: boolean = true;
@Input() paginatorDropdownAppendTo: any;
@Input() paginatorDropdownScrollHeight: string = '200px';
@Input() currentPageReportTemplate: string = '{currentPage} of {totalPages}';
@Input() showCurrentPageReport: boolean;
@Input() lazy: boolean;
@Input() emptyMessage: string = 'No records found';
@Output() onLazyLoad: EventEmitter = new EventEmitter();
@Input() style: any;
@Input() styleClass: string;
@Input() trackBy: Function = (index: number, item: any) => item;
@Input() filterBy: string;
@Input() filterLocale: string;
@Input() loading: boolean;
@Input() loadingIcon: string = 'far fa-spinner';
@Input() first: number = 0;
@Input() sortField: string;
@Input() sortOrder: number;
@Input() value: any[];
@Output() onPage: EventEmitter = new EventEmitter();
@Output() onSort: EventEmitter = new EventEmitter();
@Output() onChangeLayout: EventEmitter = new EventEmitter();
@ContentChild(Header) header;
@ContentChild(Footer) footer;
@ContentChildren(PrimeTemplate) templates: QueryList;
_value: any[];
listItemTemplate: TemplateRef;
gridItemTemplate: TemplateRef;
itemTemplate: TemplateRef;
headerTemplate: TemplateRef;
footerTemplate: TemplateRef;
paginatorLeftTemplate: TemplateRef;
paginatorRightTemplate: TemplateRef;
filteredValue: any[];
filterValue: string;
initialized: boolean;
constructor(public el: ElementRef, public cd: ChangeDetectorRef) {}
ngOnInit() {
if (this.lazy) {
this.onLazyLoad.emit(this.createLazyLoadMetadata());
}
this.initialized = true;
}
ngOnChanges(simpleChanges: SimpleChanges) {
if (simpleChanges.value) {
this._value = simpleChanges.value.currentValue;
this.updateTotalRecords();
if (!this.lazy && this.hasFilter()) {
this.filter(this.filterValue);
}
}
if (simpleChanges.sortField || simpleChanges.sortOrder) {
//avoid triggering lazy load prior to lazy initialization at onInit
if (!this.lazy || this.initialized) {
this.sort();
}
}
}
ngAfterContentInit() {
this.templates.forEach((item) => {
switch(item.getType()) {
case 'listItem':
this.listItemTemplate = item.template;
break;
case 'gridItem':
this.gridItemTemplate = item.template;
break;
case 'paginatorleft':
this.paginatorLeftTemplate = item.template;
break;
case 'paginatorright':
this.paginatorRightTemplate = item.template;
break;
case 'header':
this.headerTemplate = item.template;
break;
case 'footer':
this.footerTemplate = item.template;
break;
}
});
this.updateItemTemplate();
}
updateItemTemplate() {
switch(this.layout) {
case 'list':
this.itemTemplate = this.listItemTemplate;
break;
case 'grid':
this.itemTemplate = this.gridItemTemplate;
break;
}
}
changeLayout(layout: string) {
this.layout = layout;
this.onChangeLayout.emit({
layout: this.layout
});
this.updateItemTemplate();
this.cd.markForCheck();
}
updateTotalRecords() {
this.totalRecords = this.lazy ? this.totalRecords : (this._value ? this._value.length : 0);
}
paginate(event) {
this.first = event.first;
this.rows = event.rows;
if (this.lazy) {
this.onLazyLoad.emit(this.createLazyLoadMetadata());
}
this.onPage.emit({
first: this.first,
rows: this.rows
});
}
sort() {
this.first = 0;
if (this.lazy) {
this.onLazyLoad.emit(this.createLazyLoadMetadata());
}
else if (this.value) {
this.value.sort((data1, data2) => {
let value1 = ObjectUtils.resolveFieldData(data1, this.sortField);
let value2 = ObjectUtils.resolveFieldData(data2, this.sortField);
let result = null;
if (value1 == null && value2 != null)
result = -1;
else if (value1 != null && value2 == null)
result = 1;
else if (value1 == null && value2 == null)
result = 0;
else if (typeof value1 === 'string' && typeof value2 === 'string')
result = value1.localeCompare(value2);
else
result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0;
return (this.sortOrder * result);
});
if (this.hasFilter()) {
this.filter(this.filterValue);
}
}
this.onSort.emit({
sortField: this.sortField,
sortOrder: this.sortOrder
});
}
isEmpty() {
let data = this.filteredValue||this.value;
return data == null || data.length == 0;
}
createLazyLoadMetadata(): any {
return {
first: this.first,
rows: this.rows,
sortField: this.sortField,
sortOrder: this.sortOrder
};
}
getBlockableElement(): HTMLElement {
return this.el.nativeElement.children[0];
}
filter(filter: string, filterMatchMode:string ="contains") {
this.filterValue = filter;
if (this.value && this.value.length) {
let searchFields = this.filterBy.split(',');
this.filteredValue = FilterUtils.filter(this.value, searchFields, filter, filterMatchMode, this.filterLocale);
if (this.filteredValue.length === this.value.length ) {
this.filteredValue = null;
}
if (this.paginator) {
this.first = 0;
this.totalRecords = this.filteredValue ? this.filteredValue.length : this.value ? this.value.length : 0;
}
this.cd.markForCheck();
}
}
hasFilter() {
return this.filterValue && this.filterValue.trim().length > 0;
}
}
@Component({
selector: 'p-dataViewLayoutOptions',
template: `
`,
encapsulation: ViewEncapsulation.None
})
export class DataViewLayoutOptions {
@Input() style: any;
@Input() styleClass: string;
constructor(public dv: DataView) {}
changeLayout(event: Event, layout: string) {
this.dv.changeLayout(layout);
event.preventDefault();
}
}
@NgModule({
imports: [CommonModule,SharedModule,PaginatorModule],
exports: [DataView,SharedModule,DataViewLayoutOptions],
declarations: [DataView,DataViewLayoutOptions]
})
export class DataViewModule { }