import { AfterViewInit, Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild, SimpleChanges } from '@angular/core'; import { SelectionModel } from '@angular/cdk/collections'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { MatTableDataSource } from '@angular/material/table'; import { AlertService } from '../services/alert/alert.service'; @Component({ selector: 'dr-gen-table', templateUrl: './table.component.html', styleUrls: ['./table.component.scss'] }) export class TableComponent implements OnInit, AfterViewInit, OnChanges { @Input() selectCol = false; @Input() optionCol = false; @Input() inputColumns: { name: string, label: string }[] = []; @Input() displayedColumns: string[] = []; @Input() canAdd = false; @Input() canEdit = false; @Input() canDelete = false; @Input() bindData: any[] = []; @Output() bindDataChange: EventEmitter = new EventEmitter(); @Input() isDblClick: boolean = false; @Output() dblClick: EventEmitter = new EventEmitter(); inputColumnsTable: { name: string, label: string }[] = []; displayedColumnsTable: string[] = []; editRow: any = {}; dataSource: MatTableDataSource = new MatTableDataSource([]); selection = new SelectionModel(true, []); @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; constructor(private alertService: AlertService) { } ngOnInit(): void { this.fnInitTable(); } ngOnChanges(changes: SimpleChanges): void { if (changes.displayedColumns && (changes.displayedColumns.previousValue !== changes.displayedColumns.currentValue)) { this.fnInitTable(); } } fnInitTable() { this.displayedColumnsTable = []; this.inputColumnsTable = this.inputColumns; const ks: string[] = []; this.bindData.forEach(f => Object.keys(f).forEach(k => (!ks.includes(k)) ? ks.push(k) : null)); this.bindData.forEach((m, i) => this.displayedColumns.forEach(f => m[f] = m[f] || '')); this.displayedColumns.forEach(f => ((!!f) && (!!ks.includes(f) || true) && (!this.displayedColumnsTable.includes(f))) ? this.displayedColumnsTable.push(f) : null); if (this.displayedColumnsTable.length > 0) { if (this.displayedColumnsTable.length === 0 && this.inputColumnsTable.length > 0) { this.displayedColumnsTable = this.inputColumnsTable.map(m => m.name); } if (this.displayedColumnsTable.length > 0 && this.inputColumnsTable.length === 0) { this.inputColumnsTable = this.displayedColumnsTable.map(m => ({ name: m, label: m.toUpperCase() })); } if (this.optionCol && this.selectCol) { this.displayedColumnsTable.unshift('select'); } if (this.optionCol && (this.canEdit || this.canDelete)) { this.displayedColumnsTable.push('option'); } this.fnSetData(); } } ngAfterViewInit(): void { this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; } applyFilter(event: Event): void { const filterValue = (event.target as HTMLInputElement).value; this.dataSource.filter = filterValue.trim().toLowerCase(); if (this.dataSource.paginator) { this.dataSource.paginator.firstPage(); } } isAllSelected(): boolean { const numSelected = this.selection.selected.length; const numRows = this.dataSource.data.length; return numSelected === numRows; } masterToggle(): void { this.isAllSelected() ? this.selection.clear() : this.dataSource.data.forEach(row => this.selection.select(row)); } fnAdd(): any { Object.keys(this.editRow).forEach(k => this.editRow[k] = false); this.bindData.push({}); this.fnSetData(); this.fnEdit(this.bindData[this.bindData.length - 1], this.bindData.length - 1); } fnEdit(row: any, i: number): void { Object.keys(this.editRow).forEach(k => this.editRow[k] = false); this.editRow[i] = true; } fnSave(row: any, i: number): void { Object.keys(this.editRow).forEach(k => this.editRow[k] = false); this.fnSetData(); } fnDelete(row: any, i: number): void { this.alertService.confirm('Delete item?').subscribe(confirm => { if (confirm) { Object.keys(this.editRow).forEach(k => this.editRow[k] = false); this.bindData.splice(i, 1); this.fnSetData(); } }); } fnDeleteRange(row: any[]): void { this.alertService.confirm('Delete range?').subscribe(confirm => { if (confirm) { this.selection.clear(); this.dataSource.data = this.dataSource.data.filter(f => !row.includes(f)); this.bindData = this.dataSource.data; this.fnSetData(); } }); } fnSetData(): void { this.dataSource.data.forEach((r, i) => Object.keys(r).forEach(c => this.dataSource.data[i][c] = (!isNaN(r[c]) && r[c].toString().length > 0) ? Math.round(r[c]) : r[c])); this.dataSource.data = this.bindData; this.bindDataChange.emit(this.bindData); } fnDblClick(row: any) { if (this.isDblClick) { this.dblClick.emit(row); } } }