1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 08:13:42 +00:00

[CL-343] Create a new table component for virtual scrolling (#10113)

This creates a new component called bit-table-scroll as it's a breaking change in how tables works. We could probably conditionally support both behaviors in the existing table component if we desire.

Rather than iterating the rows in the consuming component, we now need to define a row definition, bitRowDef which provides access to the rows data through angular let- syntax. This allows the table component to own the behaviour which is needed in order to use the cdkVirtualFor directive which must be inside the cdk-virtual-scroll-viewport component.
This commit is contained in:
Oscar Hinton
2024-10-22 21:51:45 +02:00
committed by GitHub
parent 801d9a870b
commit 9b474264e6
8 changed files with 174 additions and 63 deletions

View File

@@ -0,0 +1,92 @@
import {
AfterContentChecked,
Component,
ContentChild,
Input,
OnDestroy,
TemplateRef,
Directive,
NgZone,
AfterViewInit,
ElementRef,
TrackByFunction,
} from "@angular/core";
import { TableComponent } from "./table.component";
/**
* Helper directive for defining the row template.
*
* ```html
* <ng-template bitRowDef let-row>
* <td bitCell>{{ row.id }}</td>
* </ng-template>
* ```
*/
@Directive({
selector: "[bitRowDef]",
standalone: true,
})
export class BitRowDef {
constructor(public template: TemplateRef<any>) {}
}
/**
* Scrollable table component.
*
* Utilizes virtual scrolling to render large datasets.
*/
@Component({
selector: "bit-table-scroll",
templateUrl: "./table-scroll.component.html",
providers: [{ provide: TableComponent, useExisting: TableScrollComponent }],
})
export class TableScrollComponent
extends TableComponent
implements AfterContentChecked, AfterViewInit, OnDestroy
{
/** The size of the rows in the list (in pixels). */
@Input({ required: true }) rowSize: number;
/** Optional trackBy function. */
@Input() trackBy: TrackByFunction<any> | undefined;
@ContentChild(BitRowDef) protected rowDef: BitRowDef;
/**
* Height of the thead element (in pixels).
*
* Used to increase the table's total height to avoid items being cut off.
*/
protected headerHeight = 0;
/**
* Observer for table header, applies padding on resize.
*/
private headerObserver: ResizeObserver;
constructor(
private zone: NgZone,
private el: ElementRef,
) {
super();
}
ngAfterViewInit(): void {
this.headerObserver = new ResizeObserver((entries) => {
this.zone.run(() => {
this.headerHeight = entries[0].contentRect.height;
});
});
this.headerObserver.observe(this.el.nativeElement.querySelector("thead"));
}
override ngOnDestroy(): void {
super.ngOnDestroy();
if (this.headerObserver) {
this.headerObserver.disconnect();
}
}
}