Skip to content

Commit

Permalink
docs(angular/table): add example for filtering and selection
Browse files Browse the repository at this point in the history
  • Loading branch information
mhaertwig committed May 25, 2022
1 parent 612e82a commit 19fb99c
Show file tree
Hide file tree
Showing 3 changed files with 243 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<ng-container [formGroup]="vehicleFilterForm">
<sbb-table-wrapper>
<table sbb-table>
<ng-container sbbColumnDef="select">
<th sbb-header-cell *sbbHeaderCellDef style="width: 50px">
<sbb-checkbox
(change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()"
[aria-label]="checkboxLabel()"
>
</sbb-checkbox>
</th>
<td sbb-cell *sbbCellDef="let row">
<sbb-checkbox
(click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(row) : null"
[checked]="selection.isSelected(row)"
[aria-label]="checkboxLabel(row)"
>
</sbb-checkbox>
</td>
</ng-container>
<ng-container *ngFor="let column of columns.slice(1)" [sbbColumnDef]="column">
<th sbb-header-cell *sbbHeaderCellDef style="width: 20%">{{ column }}</th>
<td sbb-cell *sbbCellDef="let element">{{ element[column] }}</td>
</ng-container>

<ng-container sbbColumnDef="filter-name">
<th sbb-header-cell *sbbHeaderCellDef class="sbb-table-filter">
<input class="sbb-input-element" formControlName="name" />
</th>
</ng-container>
<ng-container sbbColumnDef="filter-description">
<th sbb-header-cell *sbbHeaderCellDef class="sbb-table-filter">
<input class="sbb-input-element" formControlName="description" />
</th>
</ng-container>
<ng-container sbbColumnDef="filter-category">
<th sbb-header-cell *sbbHeaderCellDef class="sbb-table-filter">
<sbb-select formControlName="category" multiple placeholder="Select category...">
<sbb-option *ngFor="let category of categories" [value]="category"
>{{ category }}</sbb-option
>
</sbb-select>
</th>
</ng-container>

<ng-container sbbColumnDef="empty">
<th sbb-header-cell *sbbHeaderCellDef></th>
</ng-container>

<tr sbb-header-row *sbbHeaderRowDef="columns"></tr>
<tr
sbb-header-row
*sbbHeaderRowDef="['empty', 'empty', 'filter-name', 'empty', 'filter-description', 'filter-category']"
></tr>
<tr sbb-row *sbbRowDef="let row; columns: columns"></tr>
</table>
</sbb-table-wrapper>

<p *ngIf="dataSource.filteredData.length === 0">No keywords match your filters.</p>

<sbb-paginator class="sbb-divider-small-top" [pageSize]="5"></sbb-paginator>
</ng-container>

<h4>Selected Models</h4>
<sbb-checkbox [formControl]="includeFilteredCtrl">Include filtered out data</sbb-checkbox>
<pre>{{ selectedData | json }}</pre>
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import { SelectionModel } from '@angular/cdk/collections';
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { SbbPaginator } from '@sbb-esta/angular/pagination';
import { SbbTable, SbbTableDataSource, SbbTableFilter } from '@sbb-esta/angular/table';
import { merge, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

interface VehicleExampleItem {
position: number;
name: string;
category: 'Trainset' | 'Locomotive' | 'Railcar';
power: number;
description: string;
}

interface VehicleFilter extends SbbTableFilter {
category?: string[] | null;
name?: string | null;
description?: string | null;
}

/**
* @title Table with filtering and selection
* @order 130
*/
@Component({
selector: 'sbb-filter-select-table-example',
templateUrl: 'filter-select-table-example.html',
})
export class FilterSelectTableExample implements AfterViewInit, OnDestroy {
@ViewChild(SbbPaginator) paginator: SbbPaginator;
@ViewChild(SbbTable) table: SbbTable<VehicleExampleItem>;

columns = ['select', 'position', 'name', 'power', 'description', 'category'];
dataSource = new SbbTableDataSource<VehicleExampleItem, VehicleFilter>(VEHICLE_EXAMPLE_DATA);
selection = new SelectionModel<VehicleExampleItem>(true, []);
selectedData: VehicleExampleItem[] = [];
categories = new Set(
VEHICLE_EXAMPLE_DATA.map((vehicleExampleItem) => vehicleExampleItem.category)
);

vehicleFilterForm = new FormGroup({
category: new FormControl([] as string[]),
name: new FormControl(''),
description: new FormControl(''),
});

includeFilteredCtrl = new FormControl(true);

private _destroyed = new Subject<void>();

/** Whether the number of selected elements matches the total number of rows. */
isAllSelected() {
const numSelected = this.selection.selected.length;
const numRows = this.dataSource.filteredData.length;
return numSelected >= numRows;
}

ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
this.table.dataSource = this.dataSource;
this.vehicleFilterForm.valueChanges
.pipe(takeUntil(this._destroyed))
.subscribe((vehicleFilterForm) => {
this.dataSource.filter = vehicleFilterForm;
this.updateSelectedData();
});

merge(this.selection.changed, this.includeFilteredCtrl.valueChanges)
.pipe(takeUntil(this._destroyed))
.subscribe(() => this.updateSelectedData());
}

/** Selects all rows if they are not all selected; otherwise clear selection. */
masterToggle() {
this.isAllSelected()
? this.selection.clear()
: this.dataSource.filteredData.forEach((row) => this.selection.select(row));
}

/** Updates the list of selected data */
updateSelectedData() {
this.selectedData = this.selection.selected.filter(
(item) => this.includeFilteredCtrl.value || this.dataSource.filteredData.includes(item)
);
}

/** The label for the checkbox on the passed row */
checkboxLabel(row?: VehicleExampleItem): string {
if (!row) {
return `${this.isAllSelected() ? 'select' : 'deselect'} all`;
}
return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.position + 1}`;
}

ngOnDestroy(): void {
this._destroyed.next();
}
}

const VEHICLE_EXAMPLE_DATA: VehicleExampleItem[] = [
{
position: 1,
category: 'Railcar',
name: 'Bem 550',
power: 0,
description: 'Gleichstromfahrzeug 1500 V',
},
{
position: 2,
category: 'Trainset',
name: 'RABDe 510',
power: 2444,
description: '«Mirage», «Goldküstenexpress»',
},
{
position: 3,
category: 'Trainset',
name: 'RABDe 500',
power: 5200,
description: 'InterCity-Neigezug (ICN)',
},
{
position: 4,
category: 'Trainset',
name: 'RABe 511',
power: 4000,
description: 'KISS, RV-Dosto',
},
{ position: 5, category: 'Trainset', name: 'RABe 501', power: 6000, description: 'Giruno' },
{
position: 6,
category: 'Trainset',
name: 'RABDe 502',
power: 7500,
description: 'Twindexx IC 200, FV-Dosto',
},
{ position: 7, category: 'Trainset', name: 'ETR 610', power: 5500, description: 'Astoro' },
{
position: 8,
category: 'Trainset',
name: 'RABe 514',
power: 3200,
description: 'S-Bahn Zürich Doppelstocktriebzug (DTZ)',
},
{ position: 9, category: 'Trainset', name: 'RABe 520', power: 760, description: 'Seetal GTW' },
{ position: 10, category: 'Trainset', name: 'RABe 526', power: 1100, description: 'GTW' },
{ position: 11, category: 'Trainset', name: 'RABe 521', power: 2000, description: 'Flirt' },
{
position: 12,
category: 'Railcar',
name: 'RAe 591',
power: 835,
description: 'Churchill-Pfeil',
},
{ position: 13, category: 'Trainset', name: 'TGV PSE', power: 6450, description: 'TGV' },
{ position: 14, category: 'Trainset', name: 'TGV POS', power: 9200, description: 'TGV' },
{ position: 15, category: 'Trainset', name: 'RABe 591', power: 2310, description: 'TEE' },
{ position: 16, category: 'Railcar', name: 'RBe 4/4', power: 1988, description: 'RBe' },
{ position: 17, category: 'Railcar', name: 'RBDe 4/4', power: 1650, description: 'NPZ' },
{ position: 18, category: 'Railcar', name: 'RAe 2/4', power: 404, description: 'Roter Pfeil' },
{ position: 19, category: 'Locomotive', name: 'Re 420', power: 4700, description: 'Re 4/4 II' },
{
position: 20,
category: 'Locomotive',
name: 'Re 460',
power: 6100,
description: 'Locomotive 2000',
},
];
3 changes: 3 additions & 0 deletions src/components-examples/angular/table/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { SbbPaginationModule } from '@sbb-esta/angular/pagination';
import { SbbRadioButtonModule } from '@sbb-esta/angular/radio-button';
import { SbbSelectModule } from '@sbb-esta/angular/select';
import { SbbTableModule } from '@sbb-esta/angular/table';
import { FilterSelectTableExample } from '@sbb-esta/components-examples/angular/table/filter-select-table/filter-select-table-example';

import { ButtonsInTableExample } from './buttons-in-table/buttons-in-table-example';
import { CellActionsTableExample } from './cell-actions-table/cell-actions-table-example';
Expand Down Expand Up @@ -39,6 +40,7 @@ export {
SortableTableExample,
StickyTableExample,
ExpandableTableExample,
FilterSelectTableExample,
};

const EXAMPLES = [
Expand All @@ -54,6 +56,7 @@ const EXAMPLES = [
SortableTableExample,
StickyTableExample,
ExpandableTableExample,
FilterSelectTableExample,
];

@NgModule({
Expand Down

0 comments on commit 19fb99c

Please sign in to comment.