Components for displaying and manipulating structured data including tables, trees, pagination, and sorting with comprehensive data source integration.
Flexible data table component with sorting, pagination, and filtering support.
/**
* Data table component for displaying structured data
*/
class MatTable<T> extends CdkTable<T> {
// Extends CDK table with Material Design styling
}
/**
* Data source with built-in filtering, sorting, and pagination
*/
class MatTableDataSource<T> extends DataSource<T> {
@Input() data: T[];
@Input() filter: string;
@Input() filterPredicate: (data: T, filter: string) => boolean;
@Input() filteredData: T[];
@Input() paginator: MatPaginator | null;
@Input() sort: MatSort | null;
@Input() sortData: (data: T[], sort: MatSort) => T[];
@Input() sortingDataAccessor: (data: T, sortHeaderId: string) => string | number;
connect(collectionViewer: CollectionViewer): Observable<T[]>;
disconnect(collectionViewer: CollectionViewer): void;
_updateChangeSubscription(): void;
_filterData(data: T[]): T[];
_orderData(data: T[]): T[];
_pageData(data: T[]): T[];
_updatePaginator(filteredDataLength: number): void;
}
/**
* Text column component for simple data display
*/
class MatTextColumn<T> {
@Input() name: string;
@Input() headerText: string;
@Input() dataAccessor: (data: T, name: string) => string;
@Input() justify: 'start' | 'end' | 'center';
readonly columnDef: MatColumnDef;
readonly cell: MatCellDef;
readonly headerCell: MatHeaderCellDef;
}
/**
* Table module
*/
class MatTableModule {
// NgModule for table functionality
}Pagination controls for navigating through large datasets.
/**
* Paginator component for controlling data pagination
*/
class MatPaginator implements OnInit, OnDestroy, CanDisable, HasInitialized {
@Input() color: ThemePalette;
@Input() pageIndex: number;
@Input() length: number;
@Input() pageSize: number;
@Input() pageSizeOptions: number[];
@Input() hidePageSize: boolean;
@Input() showFirstLastButtons: boolean;
@Input() selectConfig: MatPaginatorSelectConfig;
@Input() disabled: boolean;
@Output() readonly page: EventEmitter<PageEvent>;
readonly _intl: MatPaginatorIntl;
readonly _changeDetectorRef: ChangeDetectorRef;
nextPage(): void;
previousPage(): void;
firstPage(): void;
lastPage(): void;
hasNextPage(): boolean;
hasPreviousPage(): boolean;
getNumberOfPages(): number;
_changePageSize(pageSize: number): void;
_nextButtonsDisabled(): boolean;
_previousButtonsDisabled(): boolean;
_getRangeLabel(page: number, pageSize: number, length: number): string;
}
/**
* Paginator internationalization service
*/
class MatPaginatorIntl {
readonly changes: Subject<void>;
itemsPerPageLabel: string;
nextPageLabel: string;
previousPageLabel: string;
firstPageLabel: string;
lastPageLabel: string;
getRangeLabel: (page: number, pageSize: number, length: number) => string;
}
/**
* Page change event
*/
interface PageEvent {
pageIndex: number;
previousPageIndex?: number;
pageSize: number;
length: number;
}
/**
* Paginator select configuration
*/
interface MatPaginatorSelectConfig {
disableOptionCentering?: boolean;
panelClass?: string | string[];
}
/**
* Paginator module
*/
class MatPaginatorModule {
// NgModule for paginator functionality
}Sortable table headers with multi-column sorting support.
/**
* Sortable container directive
*/
class MatSort implements OnChanges, OnDestroy, OnInit, CanDisable {
@Input('matSortActive') active: string;
@Input('matSortStart') start: SortDirection;
@Input('matSortDirection') direction: SortDirection;
@Input('matSortDisableClear') disableClear: boolean;
@Input('matSortDisabled') disabled: boolean;
@Output('matSortChange') readonly sortChange: EventEmitter<Sort>;
readonly sortables: Map<string, MatSortable>;
register(sortable: MatSortable): void;
deregister(sortable: MatSortable): void;
sort(sortable: MatSortable): void;
getNextSortDirection(sortable: MatSortable): SortDirection;
}
/**
* Sortable column header component
*/
class MatSortHeader implements CanDisable, MatSortable, OnDestroy, OnInit, AfterViewInit {
@Input('mat-sort-header') id: string;
@Input() ariaLabel: string;
@Input() start: SortDirection;
@Input() disabled: boolean;
@Input() sortActionDescription: string;
@Input() disableClear: boolean;
readonly _sort: MatSort;
readonly _columnDef: MatColumnDef;
readonly _showIndicatorHint: boolean;
readonly _disableViewStateAnimation: boolean;
_updateArrowDirection(): void;
_setAnimationTransitionState(viewState: ArrowViewStateTransition): void;
_toggleOnInteraction(): void;
_setIndicatorHintVisible(visible: boolean): void;
_setAnimationTransitionState(viewState: ArrowViewStateTransition): void;
_isSorted(): boolean;
_getArrowDirectionState(): string;
_getArrowViewState(): string;
_renderArrow(): boolean;
_getSortActionDescription(): string;
_updateSortActionDescription(): void;
}
/**
* Sort header internationalization service
*/
class MatSortHeaderIntl {
readonly changes: Subject<void>;
sortButtonLabel: (id: string) => string;
}
/**
* Sort direction type
*/
type SortDirection = 'asc' | 'desc' | '';
/**
* Sort state interface
*/
interface Sort {
active: string;
direction: SortDirection;
}
/**
* Sortable interface
*/
interface MatSortable {
id: string;
start: SortDirection;
disableClear: boolean;
}
/**
* Arrow view state transition type
*/
type ArrowViewStateTransition = 'fromTo' | 'toFrom' | 'enter' | 'leave';
/**
* Sort module
*/
class MatSortModule {
// NgModule for sort functionality
}Hierarchical data display component with nested and flat data structure support.
/**
* Tree component for displaying hierarchical data
*/
class MatTree<T, K = T> extends CdkTree<T, K> {
// Material Design tree extending CDK tree
}
/**
* Tree node directive
*/
class MatTreeNode<T, K = T> extends CdkTreeNode<T, K> {
@Input() role: 'treeitem' | 'group';
@Input() disabled: boolean;
@Input() tabIndex: number;
// Material Design tree node
}
/**
* Tree node padding directive
*/
class MatTreeNodePadding<T, K = T> extends CdkTreeNodePadding<T, K> {
@Input('matTreeNodePadding') level: number;
@Input('matTreeNodePaddingIndent') indent: number | string;
// Adds appropriate padding for tree node level
}
/**
* Tree node toggle directive
*/
class MatTreeNodeToggle<T, K = T> extends CdkTreeNodeToggle<T, K> {
@Input('matTreeNodeToggleRecursive') recursive: boolean;
// Toggle expansion/collapse of tree node
}
/**
* Tree node outlet directive
*/
class MatTreeNodeOutlet extends CdkTreeNodeOutlet {
// Outlet where tree nodes are rendered
}
/**
* Flat tree data source
*/
class MatTreeFlatDataSource<T, F, K = F> extends DataSource<F> {
constructor(
private _treeControl: FlatTreeControl<F, K>,
private _treeFlattener: MatTreeFlattener<T, F, K>,
initialData?: T[]
);
@Input() data: T[];
connect(collectionViewer: CollectionViewer): Observable<F[]>;
disconnect(): void;
}
/**
* Nested tree data source
*/
class MatTreeNestedDataSource<T> extends DataSource<T> {
constructor(private _treeControl: NestedTreeControl<T>);
@Input() data: T[];
connect(collectionViewer: CollectionViewer): Observable<T[]>;
disconnect(): void;
}
/**
* Tree flattener for converting nested to flat structure
*/
class MatTreeFlattener<T, F, K = F> {
constructor(
public transformFunction: (node: T, level: number) => F,
public getLevel: (node: F) => number,
public isExpandable: (node: F) => boolean,
public getChildren: (node: T) => Observable<T[]> | T[] | undefined | null
);
_flattenNode(node: T, level: number, resultNodes: F[], parentMap: boolean[]): F[];
_flattenChildren(children: T[], level: number, resultNodes: F[], parentMap: boolean[]): void;
flattenNodes(structuredData: T[]): F[];
expandFlattenedNodes(nodes: F[], treeControl: TreeControl<F, K>): F[];
}
/**
* Tree module
*/
class MatTreeModule {
// NgModule for tree functionality
}Usage Examples:
import { MatTableModule } from '@angular/material/table';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort';
import { MatTreeModule } from '@angular/material/tree';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
interface PeriodicElement {
name: string;
position: number;
weight: number;
symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
// ... more data
];
interface FoodNode {
name: string;
children?: FoodNode[];
}
const TREE_DATA: FoodNode[] = [
{
name: 'Fruit',
children: [
{name: 'Apple'},
{name: 'Banana'},
{name: 'Orange'}
]
},
{
name: 'Vegetables',
children: [
{name: 'Carrot'},
{name: 'Lettuce'},
{name: 'Broccoli'}
]
}
];
@Component({
imports: [
MatTableModule,
MatPaginatorModule,
MatSortModule,
MatTreeModule,
MatInputModule,
MatFormFieldModule,
MatIconModule,
MatButtonModule
],
template: `
<!-- Data Table with Sorting and Pagination -->
<mat-form-field>
<mat-label>Filter</mat-label>
<input matInput (keyup)="applyFilter($event)" placeholder="Ex. Mia">
</mat-form-field>
<mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="position">
<mat-header-cell *matHeaderCellDef mat-sort-header> No. </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
</ng-container>
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header> Name </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
</ng-container>
<ng-container matColumnDef="weight">
<mat-header-cell *matHeaderCellDef mat-sort-header> Weight </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
</ng-container>
<ng-container matColumnDef="symbol">
<mat-header-cell *matHeaderCellDef mat-sort-header> Symbol </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
<mat-paginator [pageSizeOptions]="[5, 10, 20]"
showFirstLastButtons
aria-label="Select page of periodic elements">
</mat-paginator>
<!-- Tree Display -->
<mat-tree [dataSource]="treeDataSource" [treeControl]="treeControl">
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding>
<button mat-icon-button disabled></button>
{{node.name}}
</mat-tree-node>
<mat-tree-node *matTreeNodeDef="let node; when: hasChild" matTreeNodePadding>
<button mat-icon-button matTreeNodeToggle
[attr.aria-label]="'Toggle ' + node.name">
<mat-icon class="mat-icon-rtl-mirror">
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon>
</button>
{{node.name}}
</mat-tree-node>
</mat-tree>
`
})
export class DataDisplayExample implements OnInit {
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource = new MatTableDataSource(ELEMENT_DATA);
treeControl = new NestedTreeControl<FoodNode>(node => node.children);
treeDataSource = new MatTreeNestedDataSource<FoodNode>();
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit() {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.treeDataSource.data = TREE_DATA;
}
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
if (this.dataSource.paginator) {
this.dataSource.paginator.firstPage();
}
}
hasChild = (_: number, node: FoodNode) => !!node.children && node.children.length > 0;
}