Skip to content
OGE logoOGE

Migrate from Angular Material

Material gives you primitives to assemble; OGE components carry the behaviour themselves. The move is mostly deletion: the MatTableDataSource, sort and paginator wiring becomes one grid, and mat-form-field wrappers become editors with their own label and validation.

component map defaults tables dialogs

Component map

Each Angular element has a React twin with the same options (<OgeGrid>, <OgeSelectBox>…).

Angular Material components and their OGE counterparts
Angular MaterialOGEPackage
mat-table + MatSort + mat-paginatoroge-grid (or oge-simple-table for a static table) @oge-ui/grid · @oge-ui/layout
mat-treeoge-tree-view@oge-ui/navigation
MatDialogOgeModalService.open() · oge-modal@oge-ui/overlay
MatSnackBarOgeToastService@oge-ui/overlay
mat-menu + matMenuTriggerForoge-drop-down-button · [ogeContextMenu] · oge-menu-list@oge-ui/buttons · @oge-ui/overlay
matTooltip[ogeTooltip]@oge-ui/overlay
mat-button · mat-flat-button · mat-stroked-button · mat-icon-buttonoge-button ( stylingMode: 'text' | 'contained' | 'outlined' ) @oge-ui/buttons
mat-button-toggle-groupoge-button-group@oge-ui/buttons
mat-selectoge-select-box ( oge-tag-box for multiple) @oge-ui/inputs
mat-autocompleteoge-autocomplete@oge-ui/inputs
mat-datepickeroge-date-box · oge-date-range-box@oge-ui/inputs
matInput in mat-form-fieldoge-text-box · oge-number-box · oge-text-area@oge-ui/inputs
mat-checkbox · mat-radio-group · mat-slide-toggleoge-check-box · oge-radio-group · oge-switch@oge-ui/inputs
mat-slideroge-slider · oge-range-slider@oge-ui/inputs
mat-tab-groupoge-tabs@oge-ui/tabs
mat-stepperoge-stepper@oge-ui/navigation
mat-sidenavoge-drawer@oge-ui/navigation
mat-expansion-panel · mat-accordionoge-expansion-panel · oge-accordion@oge-ui/layout
mat-card · mat-chip-set · mat-progress-bar · mat-progress-spinneroge-card · oge-chip-list · oge-progress-bar · oge-load-indicator@oge-ui/layout
mat-badgebadge input on oge-button , or oge-badge@oge-ui/buttons · @oge-ui/layout

Defaults that differ

Defaults that differ
BehaviourAngular MaterialOGE
Snack bar / toast dismisses itself no — stays until dismissed unless duration is set yes — after toastDisplayTime (4000 ms)
Tooltip side matTooltipPosition = belowtooltipPlacement = top
Tooltip delay matTooltipShowDelay = 0 tooltipShowDelayMs = 400 ms
Paging only with a mat-paginator you connect paging on the grid; without it the grid scrolls (virtual when scrolling.mode is virtual )
Sorting only with matSort + mat-sort-header on for every column with a field ; sortable turns a column off
Filtering a filterPredicate you write filterRow , headerFilter , searchPanel — accent- and case-insensitive

Tables

A Material table renders what you give it; the grid owns sorting, paging, filtering, grouping, selection, editing and export, in memory or through a server data source (see the filter contract). For a plain styled table with no behaviour, use oge-simple-table.

<!-- Material: a table you assemble — columns, sort and paginator wired by hand -->
<table mat-table [dataSource]="dataSource" matSort>
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
    <td mat-cell *matCellDef="let row">{{ row.name }}</td>
  </ng-container>
  <tr mat-header-row *matHeaderRowDef="['name']"></tr>
  <tr mat-row *matRowDef="let row; columns: ['name']"></tr>
</table>
<mat-paginator [pageSize]="20" />

<!-- OGE: the grid owns sorting, paging, filtering and virtual scrolling -->
<oge-grid [data]="rows" keyField="id" [paging]="{ pageSize: 20 }" [filterRow]="true">
  <oge-column field="name" caption="Name" />
</oge-grid>

<!-- a static, styled table without grid behaviour -->
<oge-simple-table [value]="rows" [columns]="[{ field: 'name', caption: 'Name' }]" />

Dialogs and snack bars

Both open components the same way. The OGE modal ref resolves a promise instead of exposing an observable, and the dialog closes on a backdrop click and Escape like Material's (closeOnBackdropClick, closeOnEscape).

// Material: MatDialog.open(Component, { data }) → afterClosed() observable
const ref = this.dialog.open(EditUser, { data: user, width: '480px' });
ref.afterClosed().subscribe((result) => …);

// OGE: OgeModalService.open(Component, { data }) → a ref whose closed promise carries the result
const ref = this.modals.open(EditUser, { data: user, width: 480 });
ref.closed.then(({ result }) => …);
// inside EditUser: inject(OGE_MODAL_DATA), inject(OgeModalRef).close(value)
// Material: MatSnackBar — stays until dismissed unless you pass a duration
this.snack.open('Saved', 'Undo', { duration: 3000 });

// OGE: OgeToastService — dismisses itself after 4 s by default, actions included
this.toasts.success('Saved', { action: { text: 'Undo', handler: () => this.undo() } });

Form fields

OGE editors bring their own chrome: label, labelMode, hint and error text, and they implement ControlValueAccessor, so reactive and template-driven forms keep working unchanged.

<!-- Material: mat-form-field wraps a native control -->
<mat-form-field>
  <mat-label>City</mat-label>
  <mat-select [(value)]="city">
    @for (c of cities; track c) { <mat-option [value]="c">{{ c }}</mat-option> }
  </mat-select>
</mat-form-field>

<!-- OGE: the editor carries its own label, chrome and validation messages -->
<oge-select-box label="City" [items]="cities" [(value)]="city" />

Theming

Material's Sass theme maps onto the --oge-* tokens: set --oge-accent to your primary colour and --oge-radius to your shape scale, or import a bridge. Dark mode follows your own switch through dark-class.css or the Sass theme() mixin — see Styling.