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: `
{{emptyMessage}}
`, 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 { }