import { Component, OnInit, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewChild, } from '@angular/core'; import { MwListItem } from './list.models'; import { filter, groupBy } from 'projects/core/src//utils/array.utils'; import { MwPerfectScrollBarDirective } from 'projects/core/src//directives/perfect-scrollbar.directive'; import { debounce } from 'rxjs/operators'; import { Subject, interval } from 'rxjs'; import { KeyValue } from '@angular/common'; @Component({ selector: 'mw-list', templateUrl: 'list.component.html', styleUrls: ['./list.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) export class MwListComponent implements OnInit { @Input() icon = 'chevron_right'; @Input() allowSearch = false; @Input() lastSearchString = ''; @Input() searchOnServerSide = true; @Input() groupKeyGetter: (t: MwListItem) => string; @Input() filterFieldsGetter: (t: MwListItem) => string | string[]; @Output() clickItem = new EventEmitter(); @Output() search = new EventEmitter(); @ViewChild(MwPerfectScrollBarDirective) perfectScrollBar: MwPerfectScrollBarDirective; filteredItems: MwListItem[] = []; groupedItems: Map; private allItems: MwListItem[] = []; private search$ = new Subject(); private readonly defaultFieldGetter: (t: MwListItem) => string = (t) => t.title; @Input() set items(items: MwListItem[]) { this.allItems = items || []; if (!this.searchOnServerSide) { this.filteredItems = this.filterItems( this.lastSearchString, this.allItems ); } else { this.filteredItems = this.allItems; } this.groupItems(this.filteredItems); this.scrollToTop(); } onClick(item: MwListItem): void { this.clickItem.emit(item.data); } ngOnInit(): void { this.search$ .pipe(debounce(() => interval(250))) .subscribe((searchString) => this.search.emit(searchString)); } onSearch(searchString: string): void { this.lastSearchString = (searchString && searchString.toLocaleLowerCase()) || ''; this.search$.next(searchString); if (!this.searchOnServerSide) { this.filteredItems = this.filterItems( this.lastSearchString, this.allItems ); this.groupItems(this.filteredItems); } this.scrollToTop(); } trackByFn(index: number, item: MwListItem): string { return item.title; } compareFn(a: KeyValue, b: KeyValue): number { return a.key.localeCompare(b.key); } private scrollToTop(): void { if (this.perfectScrollBar) { this.perfectScrollBar.scrollToTop(); } } private filterItems(searchString: string, items: MwListItem[]): MwListItem[] { return filter( items, searchString, this.filterFieldsGetter || this.defaultFieldGetter ); } private groupItems(items: MwListItem[]): void { this.groupedItems = this.groupKeyGetter && groupBy(items, this.groupKeyGetter); } }