Add Megafilter to reference tables

master
Max Ehrlicher-Schmidt 4 years ago
parent 78d77ad1a8
commit 33c859b4f1

@ -1,5 +1,15 @@
<div class="table-page-wrapper">
<div class="table-control">
<button
mat-raised-button
color="primary"
class="table-control-button"
*ngIf="columnFiltersAreSet()"
i18n
(click)="resetColumnFilters()"
>
Filter zurücksetzen
</button>
<div *ngIf="editableReferences">
<app-autocomplete-select
[editable]="editable"
@ -10,26 +20,6 @@
(selectedElementChange)="addReference($event)"
></app-autocomplete-select>
</div>
<mat-form-field class="filter">
<mat-label>Tabelle filtern</mat-label>
<input
matInput
[(ngModel)]="tableFilterString"
(ngModelChange)="newFilterStringValue()"
placeholder="Suchbegriff eingeben..."
/>
<button
mat-button
*ngIf="tableFilterString"
matSuffix
mat-icon-button
aria-label="Clear"
(click)="tableFilterString = ''; applyTableFilter()"
color="accent"
>
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
<mat-paginator
[pageSizeOptions]="[15, 25]"
showFirstLastButtons
@ -40,6 +30,36 @@
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Filter Header Row -->
<ng-container
*ngFor="let column of columnInfo"
[matColumnDef]="column.dataPath + '.filter'"
[sticky]="isStickyColumn(column.dataPath)"
><th mat-header-cell *matHeaderCellDef>
<app-filter-row
*ngIf="filters.columnFilters[column.dataPath]?.isSet"
[column]="column"
[(filter)]="filters.columnFilters[column.dataPath]"
(filtersChange)="newFilterValue()"
></app-filter-row>
<button
mat-icon-button
matTooltip="Filter hinzufügen"
*ngIf="!filters.columnFilters[column.dataPath]?.isSet"
(click)="
filters.columnFilters[column.dataPath].isSet = true;
setTableFilterRowHeight()
"
>
<mat-icon>filter_list</mat-icon>
</button>
</th>
</ng-container>
<!-- empty filter cell -->
<ng-container matColumnDef="buttons.filter">
<th mat-header-cell *matHeaderCellDef></th>
</ng-container>
<!-- Other Columns -->
<ng-container
*ngFor="let column of columnInfo"
@ -96,7 +116,16 @@
</ng-container>
<!-- Table Definition -->
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr
mat-header-row
*matHeaderRowDef="displayedFilterColumns; sticky: true"
#filterRow
></tr>
<tr
mat-header-row
#headerRow
*matHeaderRowDef="displayedColumns; sticky: true"
></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>

@ -1,5 +1,6 @@
import {
Component,
ElementRef,
EventEmitter,
Input,
Output,
@ -11,7 +12,7 @@ import { SchemaService } from 'src/app/services/schema.service';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { FormControl, FormGroup } from '@angular/forms';
import { customTableFilterFunction } from 'src/app/helperFunctions/customTableFilterFunction';
import { Subject } from 'rxjs/internal/Subject';
import { debounceTime } from 'rxjs/internal/operators/debounceTime';
@ -28,6 +29,7 @@ export class ReferenceTableComponent {
translation: string;
sticky?: boolean;
type?: string;
list?: boolean; //whether the type is a list
link?: (row: any) => string;
}[] = [];
@ -77,6 +79,9 @@ export class ReferenceTableComponent {
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
@ViewChild('filterRow', { read: ElementRef }) filterRow: ElementRef;
@ViewChild('headerRow', { read: ElementRef }) headerRow: ElementRef;
displayedColumns: string[] = [];
/** data source of the table */
@ -86,8 +91,9 @@ export class ReferenceTableComponent {
reloadingTable = false;
tableFilterString = '';
filterStringChanged: Subject<string> = new Subject<string>();
displayedFilterColumns = [];
filters: any = {};
filterChanged: Subject<any> = new Subject<any>();
constructor(private schemaService: SchemaService) {}
@ -99,16 +105,26 @@ export class ReferenceTableComponent {
if (this.editableReferences) {
this.displayedColumns.push('buttons');
}
this.displayedFilterColumns = this.displayedColumns.map(
(columnName) => columnName + '.filter'
);
this.filterStringChanged
.pipe(debounceTime(400))
.subscribe(() => this.applyTableFilter());
this.dataSource.filterPredicate = customTableFilterFunction;
this.resetFilters();
}
ngAfterViewInit() {
this.setTableFilterRowHeight();
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.dataSource.filter = (this.filters as unknown) as string;
this.filterChanged.pipe(debounceTime(400)).subscribe(() => {
this.applyFilters();
});
this.dataSource.sortingDataAccessor = (item, columnName) => {
if (typeof item[columnName] === 'string') {
return item[columnName].toLocaleLowerCase();
@ -152,9 +168,9 @@ export class ReferenceTableComponent {
(element) => element.id === row.id
);
if (index !== -1) {
this.dataSource.data.splice(index, 1);
this.dataSource.data = this.dataSource.data; //needed to trigger update lol
this.onReferenceChange();
this.dataSource.data.splice(index, 1);
this.dataSource.data = this.dataSource.data; //needed to trigger update lol
this.onReferenceChange();
}
// show it again in the selection
@ -166,8 +182,7 @@ export class ReferenceTableComponent {
addReference(row: any) {
this.dataSource.data = [flatten(row), ...this.dataSource.data];
this.idsOfObjectsToHide = [row.id, ...this.idsOfObjectsToHide];
this.tableFilterString = '';
this.applyTableFilter();
this.resetFilters();
this.onReferenceChange();
}
@ -175,14 +190,6 @@ export class ReferenceTableComponent {
return this.dataSource.data.find((row) => row.id === id);
}
newFilterStringValue(): void {
this.filterStringChanged.next(this.tableFilterString);
}
applyTableFilter() {
this.dataSource.filter = this.tableFilterString;
}
onReferenceChange() {
const ids = [];
for (const element of this.data) {
@ -190,4 +197,58 @@ export class ReferenceTableComponent {
}
this.referenceIds.emit(ids);
}
/** Filter functions **************************************************************/
newFilterValue(): void {
this.filterChanged.next(this.filters);
}
applyFilters(): void {
this.dataSource.filter = (this.filters as unknown) as string;
}
columnFiltersAreSet(): boolean {
for (const filterObject of Object.keys(this.filters.columnFilters)) {
if (this.filters.columnFilters[filterObject].isSet) {
return true;
}
}
return false;
}
resetColumnFilters() {
this.filters['columnFilters'] = [];
for (const column of this.columnInfo) {
this.filters.columnFilters[column.dataPath] = {
isSet: false,
value: null,
minValue: {},
maxValue: {},
fromValue: {},
toValue: {},
type: column.type,
list: column.list,
options: {},
};
}
this.setTableFilterRowHeight();
this.applyFilters();
}
resetFilters() {
this.filters = [];
this.resetColumnFilters();
}
setTableFilterRowHeight() {
setTimeout(() => {
const filterRowHeight = this.filterRow.nativeElement.clientHeight;
const headerRowCells = Array.from(
this.headerRow.nativeElement.children as HTMLCollectionOf<HTMLElement>
);
for (let i = 0; i < headerRowCells.length; i++) {
headerRowCells[i].style.top = filterRowHeight + 'px';
}
});
}
}

@ -354,12 +354,12 @@
<tr
mat-header-row
*matHeaderRowDef="displayedFilterColumns; sticky: true"
class="filter-row"
#filterRow
></tr>
<tr
mat-header-row
*matHeaderRowDef="displayedColumns; sticky: true"
class="header-row"
#headerRow
></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>

@ -7,6 +7,7 @@ import {
ViewChild,
AfterViewInit,
ChangeDetectorRef,
ElementRef,
} from '@angular/core';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { flatten } from 'src/app/helperFunctions/flattenObject';
@ -22,7 +23,6 @@ import { ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/internal/operators/debounceTime';
import { SelectObjectDialogComponent } from '../select-object-dialog/select-object-dialog.component';
import { filter } from 'rxjs/operators';
@Component({
selector: 'app-table',
@ -66,6 +66,9 @@ export class TableComponent implements AfterViewInit {
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
@ViewChild('filterRow', { read: ElementRef }) filterRow: ElementRef;
@ViewChild('headerRow', { read: ElementRef }) headerRow: ElementRef;
additionalColumnsFront: string[] = [];
additionalColumnsBack: string[] = ['buttons'];
displayedColumns: string[] = [];
@ -456,6 +459,7 @@ export class TableComponent implements AfterViewInit {
};
}
this.setTableFilterRowHeight();
this.applyFilters();
}
resetFilters() {
@ -465,11 +469,9 @@ export class TableComponent implements AfterViewInit {
setTableFilterRowHeight() {
setTimeout(() => {
const filterRowHeight = document.getElementsByClassName('filter-row')[0]
.clientHeight;
const filterRowHeight = this.filterRow.nativeElement.clientHeight;
const headerRowCells = Array.from(
document.getElementsByClassName('header-row')[0]
.children as HTMLCollectionOf<HTMLElement>
this.headerRow.nativeElement.children as HTMLCollectionOf<HTMLElement>
);
for (let i = 0; i < headerRowCells.length; i++) {
headerRowCells[i].style.top = filterRowHeight + 'px';

@ -250,7 +250,7 @@ export class BikeComponent implements OnInit {
},
{
type: 'ReferenceTable',
title: 'Equipment',
title: 'Equipments',
dataPath: 'equipment',
dataService: null,
columnInfo: [

Loading…
Cancel
Save