Container-breakpoint-observer

Observes a container element for provided queries and notifies the consumer if a query is matching or not

Observes the created container for provided queries and notifies the consumer if a query is matching or not. Use the observe with a query to start monitoring. The queries have the same syntax as the browsers media queries (e.g.: (min-width: 300px)).

Note: Only min-width, max-width, min-height and max-height are supported.

´ Loading interactive demo...
<dt-container-breakpoint-observer> <p>This is some placeholder text</p> <button dt-button>Some button</button> </dt-container-breakpoint-observer> export class ContainerBreakpointObserverDefaultExample implements OnInit { @ViewChild(DtContainerBreakpointObserver, { static: true }) breakpointObserver: DtContainerBreakpointObserver; ngOnInit(): void { this.breakpointObserver.observe('(min-width: 400px)').subscribe(event => { // tslint:disable-next-line: no-console console.log(`Matches '(min-width: 400px)':`, event.matches); }); } } <dt-container-breakpoint-observer> <p>This is some placeholder text</p> <button dt-button>Some button</button> </dt-container-breakpoint-observer> export class ContainerBreakpointObserverDefaultExample implements OnInit { @ViewChild(DtContainerBreakpointObserver, { static: true }) breakpointObserver: DtContainerBreakpointObserver; ngOnInit(): void { this.breakpointObserver.observe('(min-width: 400px)').subscribe(event => { // tslint:disable-next-line: no-console console.log(`Matches '(min-width: 400px)':`, event.matches); }); } }

Experimental

Why is it experimental:

  • As this component heavily uses the Intersection Observer and some overlaying elements we do not have to rely on the browser's resize event and should therefor theoretically get much better performance. We still want to monitor the use-cases and performance figures before we fully introduce this feature.
  • This component just now has one method where you can monitor a media query. More directives and APIs are planed to make it easier to use it.
  • Proper UI testing is still missing.

Imports

You have to import the DtContainerBreakpointObserverModule when you want to use the <dt-container-breakpoint-observer>.

@NgModule({
  imports: [DtContainerBreakpointObserverModule],
})
class MyModule {}

Methods

Name Params Return type Description
observe string |string[] Observable<DtBreakpointState> Start observing the container with the provided media query/queries. The observable will provide you a DtBreakpointState object which tells you if all media queries are currently matching (or not) and which of the individual breakpoints are matching.

Responsive Table

Using the breakpoint observer creating a responsive table got easier:

´ Loading interactive demo...
<dt-container-breakpoint-observer> <dt-table [dataSource]="dataSource"> <ng-container dtColumnDef="host" dtColumnAlign="text"> <dt-header-cell *dtHeaderCellDef>Host</dt-header-cell> <dt-cell *dtCellDef="let row">{{ row.host }}</dt-cell> </ng-container> <ng-container dtColumnDef="cpu" dtColumnAlign="text"> <dt-header-cell *dtHeaderCellDef>CPU</dt-header-cell> <dt-cell *dtCellDef="let row">{{ row.cpu }}</dt-cell> </ng-container> <ng-container dtColumnDef="memory" dtColumnAlign="number"> <dt-header-cell *dtHeaderCellDef>Memory</dt-header-cell> <dt-cell *dtCellDef="let row">{{ row.memory }}</dt-cell> </ng-container> <ng-container dtColumnDef="traffic" dtColumnAlign="control"> <dt-header-cell *dtHeaderCellDef>Network traffic</dt-header-cell> <dt-cell *dtCellDef="let row">{{ row.traffic }}</dt-cell> </ng-container> <ng-container dtColumnDef="details" dtColumnAlign="number"> <dt-header-cell *dtHeaderCellDef>Details</dt-header-cell> <dt-expandable-cell *dtCellDef></dt-expandable-cell> </ng-container> <dt-header-row *dtHeaderRowDef="_headerColumns"></dt-header-row> <dt-row *dtRowDef=" let row; columns: ['host', 'cpu', 'memory', 'traffic']; let rowIndex = index; when: !_isTableNarrow " ></dt-row> <dt-expandable-row *dtRowDef=" let row; columns: ['host', 'cpu', 'details']; let rowIndex = index; when: _isTableNarrow " > <ng-template dtExpandableRowContent> <dt-key-value-list> <dt-key-value-list-item> <dt-key-value-list-key>Memory</dt-key-value-list-key> <dt-key-value-list-value>{{ row.memory }}</dt-key-value-list-value> </dt-key-value-list-item> <dt-key-value-list-item> <dt-key-value-list-key>Traffic</dt-key-value-list-key> <dt-key-value-list-value>{{ row.traffic }}</dt-key-value-list-value> </dt-key-value-list-item> </dt-key-value-list> </ng-template> </dt-expandable-row> </dt-table> </dt-container-breakpoint-observer> export class TableResponsiveExample implements OnInit { dataSource: HostMetricResponsive[] = [ { host: 'et-demo-2-win4', cpu: '30 %', memory: '38 % of 5.83 GB', traffic: '98.7 Mbit/s', isNarrow: false, }, { host: 'et-demo-2-win3', cpu: '26 %', memory: '46 % of 6 GB', traffic: '625 Mbit/s', isNarrow: false, }, { host: 'docker-host2', cpu: '25.4 %', memory: '38 % of 5.83 GB', traffic: '419 Mbit/s', isNarrow: false, }, { host: 'et-demo-2-win1', cpu: '23 %', memory: '7.86 % of 5.83 GB', traffic: '98.7 Mbit/s', isNarrow: false, }, ]; _headerColumns = new Set(['host', 'cpu']); @ViewChild(DtContainerBreakpointObserver, { static: true }) _tableBreakpointObserver: DtContainerBreakpointObserver; @ViewChild(DtTable, { static: true }) _table: DtTable<any>; // tslint:disable-line: no-any private _tableNarrow = false; constructor(private _changeDetectorRef: ChangeDetectorRef) {} ngOnInit(): void { this._tableBreakpointObserver .observe('(max-width: 1000px)') .subscribe(event => { this._tableNarrow = event.matches; // Show/hide header columns respecting // whether the table is in the narrow state if (this._tableNarrow) { this._headerColumns.delete('memory'); this._headerColumns.delete('traffic'); this._headerColumns.add('details'); } else { this._headerColumns.add('memory'); this._headerColumns.add('traffic'); this._headerColumns.delete('details'); } // Call render because we need to notify // the table that something has changes this._table.renderRows(); this._changeDetectorRef.markForCheck(); }); } /** * Whether the table is in the narrow state. * This needs to be an arrow function because the table calls it with a wrong `this`. */ _isTableNarrow = () => this._tableNarrow; } <dt-container-breakpoint-observer> <dt-table [dataSource]="dataSource"> <ng-container dtColumnDef="host" dtColumnAlign="text"> <dt-header-cell *dtHeaderCellDef>Host</dt-header-cell> <dt-cell *dtCellDef="let row">{{ row.host }}</dt-cell> </ng-container> <ng-container dtColumnDef="cpu" dtColumnAlign="text"> <dt-header-cell *dtHeaderCellDef>CPU</dt-header-cell> <dt-cell *dtCellDef="let row">{{ row.cpu }}</dt-cell> </ng-container> <ng-container dtColumnDef="memory" dtColumnAlign="number"> <dt-header-cell *dtHeaderCellDef>Memory</dt-header-cell> <dt-cell *dtCellDef="let row">{{ row.memory }}</dt-cell> </ng-container> <ng-container dtColumnDef="traffic" dtColumnAlign="control"> <dt-header-cell *dtHeaderCellDef>Network traffic</dt-header-cell> <dt-cell *dtCellDef="let row">{{ row.traffic }}</dt-cell> </ng-container> <ng-container dtColumnDef="details" dtColumnAlign="number"> <dt-header-cell *dtHeaderCellDef>Details</dt-header-cell> <dt-expandable-cell *dtCellDef></dt-expandable-cell> </ng-container> <dt-header-row *dtHeaderRowDef="_headerColumns"></dt-header-row> <dt-row *dtRowDef=" let row; columns: ['host', 'cpu', 'memory', 'traffic']; let rowIndex = index; when: !_isTableNarrow " ></dt-row> <dt-expandable-row *dtRowDef=" let row; columns: ['host', 'cpu', 'details']; let rowIndex = index; when: _isTableNarrow " > <ng-template dtExpandableRowContent> <dt-key-value-list> <dt-key-value-list-item> <dt-key-value-list-key>Memory</dt-key-value-list-key> <dt-key-value-list-value>{{ row.memory }}</dt-key-value-list-value> </dt-key-value-list-item> <dt-key-value-list-item> <dt-key-value-list-key>Traffic</dt-key-value-list-key> <dt-key-value-list-value>{{ row.traffic }}</dt-key-value-list-value> </dt-key-value-list-item> </dt-key-value-list> </ng-template> </dt-expandable-row> </dt-table> </dt-container-breakpoint-observer> export class TableResponsiveExample implements OnInit { dataSource: HostMetricResponsive[] = [ { host: 'et-demo-2-win4', cpu: '30 %', memory: '38 % of 5.83 GB', traffic: '98.7 Mbit/s', isNarrow: false, }, { host: 'et-demo-2-win3', cpu: '26 %', memory: '46 % of 6 GB', traffic: '625 Mbit/s', isNarrow: false, }, { host: 'docker-host2', cpu: '25.4 %', memory: '38 % of 5.83 GB', traffic: '419 Mbit/s', isNarrow: false, }, { host: 'et-demo-2-win1', cpu: '23 %', memory: '7.86 % of 5.83 GB', traffic: '98.7 Mbit/s', isNarrow: false, }, ]; _headerColumns = new Set(['host', 'cpu']); @ViewChild(DtContainerBreakpointObserver, { static: true }) _tableBreakpointObserver: DtContainerBreakpointObserver; @ViewChild(DtTable, { static: true }) _table: DtTable<any>; // tslint:disable-line: no-any private _tableNarrow = false; constructor(private _changeDetectorRef: ChangeDetectorRef) {} ngOnInit(): void { this._tableBreakpointObserver .observe('(max-width: 1000px)') .subscribe(event => { this._tableNarrow = event.matches; // Show/hide header columns respecting // whether the table is in the narrow state if (this._tableNarrow) { this._headerColumns.delete('memory'); this._headerColumns.delete('traffic'); this._headerColumns.add('details'); } else { this._headerColumns.add('memory'); this._headerColumns.add('traffic'); this._headerColumns.delete('details'); } // Call render because we need to notify // the table that something has changes this._table.renderRows(); this._changeDetectorRef.markForCheck(); }); } /** * Whether the table is in the narrow state. * This needs to be an arrow function because the table calls it with a wrong `this`. */ _isTableNarrow = () => this._tableNarrow; }