Grid Pro
The @genesislcap/grid-pro
package provides a collection of grid-related components and utilities for Genesis applications.
Features
- Easy integration: Quick setup with modern JavaScript frameworks and libraries.
- Customizable: Support for custom headers, mapping values, text formatting, custom cell-renderers and more.
- Flexible: Grid-pro makes it easy by supporting filtering, editing, sorting, pagination (depending on configuration).
- Events and callbacks: Large number of events and callbacks provided by the grid. Details here.
- Simple Data or Connected Data: Two main use cases for Grid Pro:
- Simple Data: When you have your own data model and flow (JSON, external/custom REST APIs, etc) but still want to use a rich data grid component with all its features.
- Connected Data: When you have a Data Server or Request Server available and you don't want to worry about handling data transformations, updates, deletes and cell renderers.
- State persistence: Ability to save and restore grid state.
- Row models: Support for both client-side and server-side row models.
Enterprise features and licensing
Important: Some Grid Pro features require AG Grid Enterprise licensing and module registration:
- Status Bar Components: All status bar functionality (
with-status-bar
,statusBarConfig
) requires AG Grid Enterprise - Server-Side Row Model: Server-side datasource requires
@ag-grid-enterprise/server-side-row-model
- Advanced Filtering: Some advanced filtering features may require Enterprise modules
- Excel Export: Excel export functionality requires AG Grid Enterprise
For production use, you must obtain appropriate AG Grid Enterprise licenses. Contact AG Grid for licensing information.
Enterprise module registration
REQUIRED for Status Bar and Server-Side Datasource Features
If you plan to use Status Bar components (with-status-bar
) or Server-Side datasource (<grid-pro-server-side-datasource>
), you MUST register the appropriate AG Grid Enterprise modules:
import { ModuleRegistry } from '@ag-grid-community/core';
// Required for Status Bar components (with-status-bar, statusBarConfig)
import { StatusBarModule } from '@ag-grid-enterprise/status-bar';
// Required for Server-Side datasource (<grid-pro-server-side-datasource>)
import { ServerSideRowModelModule } from '@ag-grid-enterprise/server-side-row-model';
// Register the enterprise modules you need
ModuleRegistry.registerModules([
StatusBarModule, // Required for: with-status-bar, statusBarConfig
ServerSideRowModelModule, // Required for: <grid-pro-server-side-datasource>
]);
Set-up
Make sure the required grid components are registered with your design system. Depending on how the app was created this might have been setup for you automatically (genx cli / create). The design system name might vary (you can create a custom one for your app), using rapid in this example.
import { provideDesignSystem, baseComponents } from '@genesislcap/rapid-design-system';
import { rapidGridComponents } from '@genesislcap/rapid-grid-pro';
provideDesignSystem().register(baseComponents, rapidGridComponents);
If you're unsure where to register the component, search for the provideDesignSystem
method in your project.
Basic usage
Local data (simple data setup without a datasource component)
In this example, you'll see how to pass your data directly to the grid. The only thing you need to do is to bind a data structure to the :rowData
attribute.
- TypeScript
- Angular
import { ColDef, GridOptions } from '@ag-grid-community/core';
import { GridPro } from '@genesislcap/grid-pro';
import { customElement, DOM, GenesisElement, html, observable, ref } from '@genesislcap/web-core';
@customElement({
name: 'simple-grid-example',
template: html`
<rapid-grid-pro ${ref('grid')}></rapid-grid-pro>
`,
})
export class SimpleGridExample extends GenesisElement {
@observable
public grid: GridPro;
private columnDefs: ColDef[] = [
{ headerName: '#', colId: 'rowNum', valueGetter: 'node.id', width: 80, pinned: 'left' },
{ headerName: 'Athlete', field: 'athlete', width: 150, pinned: 'left' },
{ headerName: 'Age', field: 'age', width: 90, pinned: 'left' },
{ headerName: 'Country', field: 'country', width: 150 },
{ headerName: 'Year', field: 'year', width: 90 },
{
headerName: 'Date',
field: 'date',
width: 110,
filter: 'agDateColumnFilter',
filterParams: {
buttons: ['apply', 'reset'],
browserDatePicker: true,
comparator: (filterLocalDateAtMidnight, cellValue) => {
// Handling '29/08/2004' date format - adjust as need to match your date format
// https://www.ag-grid.com/javascript-data-grid/filter-date/
const dateAsString = cellValue;
if (dateAsString == null) return -1;
const dateParts = dateAsString.split('/');
const cellDate = new Date(
Number(dateParts[2]),
Number(dateParts[1]) - 1,
Number(dateParts[0]),
);
if (filterLocalDateAtMidnight.getTime() === cellDate.getTime()) {
return 0;
}
if (cellDate < filterLocalDateAtMidnight) {
return -1;
}
if (cellDate > filterLocalDateAtMidnight) {
return 1;
}
return 0;
},
},
},
{ headerName: 'Sport', field: 'sport', width: 150, editable: true },
{ headerName: 'Gold', field: 'gold', width: 100 },
{ headerName: 'Silver', field: 'silver', width: 100 },
{ headerName: 'Bronze', field: 'bronze', width: 100 },
{ headerName: 'Total', field: 'total', width: 100, pinned: 'right' },
];
private rowData = [
{
athlete: 'Michael Phelps',
age: 27,
country: 'United States',
year: 2012,
date: '12/08/2012',
sport: 'Swimming',
gold: 4,
silver: 2,
bronze: 0,
total: 6,
},
{
athlete: 'Natalie Coughlin',
age: 25,
country: 'United States',
year: 2008,
date: '24/08/2008',
sport: 'Swimming',
gold: 1,
silver: 2,
bronze: 3,
total: 6,
isActionDisabled: true,
},
// ...
];
private gridOptions: GridOptions = {
defaultColDef: {
resizable: true,
filter: true,
},
columnDefs: this.columnDefs,
rowData: this.rowData,
};
connectedCallback() {
super.connectedCallback();
DOM.queueUpdate(() => {
this.grid.gridOptions = this.gridOptions;
});
}
}
import { Component, ViewChild, ElementRef } from '@angular/core';
@Component({
selector: 'simple-grid-example',
template: `<rapid-grid-pro #grid></rapid-grid-pro>`,
})
export class SimpleGridExample {
@ViewChild('grid') grid: ElementRef;
private columnDefs = [
{ headerName: 'Make', field: 'make', sortable: true, filter: true },
{ headerName: 'Model', field: 'model', sortable: true, filter: true },
{ headerName: 'Price', field: 'price', sortable: true, filter: true },
{ headerName: 'Year', field: 'year', sortable: true, filter: true },
{ headerName: 'Color', field: 'color', sortable: true, filter: true },
];
private rowData = [
{ make: 'Toyota', model: 'Celica', price: 35000, year: 2021, color: 'red' },
{ make: 'Ford', model: 'Mondeo', price: 32000, year: 2020, color: 'blue' },
{ make: 'Porsche', model: 'Boxster', price: 72000, year: 2022, color: 'green' },
{ make: 'Subaru', model: 'Impreza', price: 25000, year: 2019, color: 'yellow' },
{ make: 'Nissan', model: 'Sentra', price: 20000, year: 2018, color: 'black' },
{ make: 'Chevrolet', model: 'Camaro', price: 40000, year: 2020, color: 'white' },
{ make: 'BMW', model: 'M3', price: 60000, year: 2021, color: 'silver' },
{ make: 'Audi', model: 'A4', price: 45000, year: 2022, color: 'orange' },
{ make: 'Mercedes', model: 'C-Class', price: 50000, year: 2020, color: 'purple' },
{ make: 'Volkswagen', model: 'Golf', price: 30000, year: 2019, color: 'brown' },
// ...
];
loadGrid() {
if (this.grid && this.grid.nativeElement) {
this.grid.nativeElement.gridOptions = {
defaultColDef: {
resizable: true,
filter: true,
},
columnDefs: this.columnDefs,
rowData: this.rowData,
};
}
}
}
Note: In your Angular module, make sure to include
CUSTOM_ELEMENTS_SCHEMA
:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@NgModule({
declarations: [SimpleGridExample],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
Grid attributes
The <grid-pro>
element supports the following attributes and properties:
Attribute | Type | Default | Description |
---|---|---|---|
:rowData | any[] | - | Manual data: Array of row data for scenarios where you set data manually without using datasource components. |
:gridComponents | {[componentName: string]: any} | - | Custom components: Object containing custom AG Grid components (cell renderers, editors, filters). |
:eventsAndCallbacks | GridProEventsAndCallbacks | - | AG Grid events: Object containing AG Grid event handlers and callbacks. |
:gridFontFace | string | defaultAgGridFontFace | Font configuration: Font face configuration for AG Grid themes. |
auto-cell-renderer-by-type | boolean | false | Genesis-specific: Enable automatic cell renderer selection by data type. |
only-template-col-defs | boolean | false | Genesis-specific: Use only template-defined column definitions, ignore metadata. |
grid-autosizing | boolean | false | Important: Controls automatic column sizing on interaction. Disables manual column widths and local storage persistence of widths. |
add-index | number | 0 | Index position for new rows when using applyTransaction or applyTransactionAsync . |
async-add | boolean | false | Use applyTransactionAsync for add transactions (better performance for large datasets). |
async-remove | boolean | false | Use applyTransactionAsync for remove transactions (better performance for large datasets). |
async-update | boolean | true | Use applyTransactionAsync for update transactions (enabled by default for performance). |
enable-cell-flashing | boolean | false | Enable cell flashing animations when cell values change. |
enable-row-flashing | boolean | false | Enable row flashing animations for add transactions. |
enabled-row-flashing | boolean | false | @deprecated - Use enable-row-flashing instead. |
persist-column-state-key | string | - | Key for persisting column state in local browser or KV storage. Essential for maintaining user preferences. |
persist-filter-model-key | string | - | Key for persisting filter model in local browser or KV storage. Maintains filter state across sessions. |
header-case-type | GridProCaseType | CONSTANT_CASE | Transform header names: camelCase , capitalCase , dotCase , headerCase , noCase , paramCase , pascalCase , pathCase , sentenceCase , snakeCase . |
column-component-name | string | grid-pro-column | Internal: Name of the column component to use. |
header-height | number | - | Custom header height in pixels. Overrides theme defaults. |
row-height | number | - | Custom row height in pixels. Overrides theme defaults. |
theme | string | alpine | AG Grid theme name. Available: alpine , alpine-dark , balham , balham-dark , material . |
pagination | boolean | false | Enables pagination. Basic pagination works with AG Grid Community edition. Enterprise features like custom pagination components require AG Grid Enterprise. Works with both client-side and server-side datasources. |
pagination-page-size | number | 25 | Number of rows per page when pagination is enabled. |
with-status-bar | boolean | false | Enterprise Feature: Enables status bar at bottom of grid. Requires AG Grid Enterprise module. |
:statusBarConfig | GridProStatusBarConfig | DEFAULT_STATUS_BAR_CONFIG | Enterprise Feature: Configuration for status bar components. Must use binding syntax with observable property. |
Status bar configuration
Enterprise License Required: Status bar functionality requires the AG Grid Enterprise license and the StatusBarModule
to be registered (see Enterprise Module Registration above). Status bar components will only be displayed if the Enterprise module is properly licensed and configured.
Important Datasource Behavior:
- Client-side datasources: All status bar components are available (
rows
,maxRows
,loadMore
,reload
,aggregation
) - Server-side datasources:
loadMore
component is automatically disabled and will not be shown, even if configured
interface GridProStatusBarConfig {
rows?: boolean; // Enable row count component (default: false)
maxRows?: boolean; // Enable max rows label-value component (default: false)
loadMore?: boolean | GridProStatusBarLoadMoreConfig; // Enable/configure load more button (CLIENT-SIDE ONLY)
reload?: boolean | GridProStatusBarReloadConfig; // Enable/configure reload button
aggregation?: boolean; // Enable aggregation component (default: false)
}
interface GridProStatusBarLoadMoreConfig {
onLoadMore?: () => void; // Custom callback function (defaults to datasource.loadMore())
appearance?: string; // Button appearance: 'accent', 'lightweight', 'neutral', 'outline', 'stealth'
tooltip?: string; // Custom tooltip text
}
interface GridProStatusBarReloadConfig {
onReload?: () => void; // Custom callback function (defaults to datasource restart/reload)
icon?: string; // Custom icon name (default: 'refresh')
tooltip?: string; // Custom tooltip text
}
Status Bar Component Availability by Datasource Type:
Component | Client-Side Datasource | Server-Side Datasource | Description |
---|---|---|---|
rows | Available | Available | Shows row count information |
maxRows | Available | Available | Shows maximum rows limit |
loadMore | Available | Disabled | Load more button (infinite scroll alternative) |
reload | Available | Available | Reload/refresh button |
aggregation | Available | Available | Shows aggregation values for selected columns |
Complete usage examples
1. Grid Pro with client-side datasource and status bar (loadMore
is enabled by default)
@customElement({
name: 'client-side-grid-example',
template: html`
<grid-pro
pagination
pagination-page-size="50"
with-status-bar
:statusBarConfig="${(x) => x.clientStatusBarConfig}"
persist-column-state-key="client-grid-columns"
persist-filter-model-key="client-grid-filters"
enable-row-flashing
enable-cell-flashing
header-case-type="headerCase"
theme="alpine-dark"
async-update
auto-cell-renderer-by-type>
<grid-pro-client-side-datasource
resource-name="ALL_TRADES"
max-rows="1000"
></grid-pro-client-side-datasource>
</grid-pro>
`
})
export class ClientSideGridExample extends GenesisElement {
// Client-side datasource: ALL status bar components available
@observable clientStatusBarConfig: GridProStatusBarConfig = {
rows: true, // Available
maxRows: true, // Available
loadMore: { // Available - shows load more button
appearance: 'accent',
tooltip: 'Load more trades from server'
},
reload: { // Available
tooltip: 'Refresh all trade data'
},
aggregation: true // Available - shows aggregation values
};
}
2. Grid Pro with server-side datasource and status bar (loadMore
is automatically disabled)
@customElement({
name: 'server-side-grid-example',
template: html`
<grid-pro
pagination
pagination-page-size="100"
with-status-bar
:statusBarConfig="${(x) => x.serverStatusBarConfig}"
persist-column-state-key="server-grid-columns"
enable-row-flashing
theme="balham">
<grid-pro-server-side-datasource
resource-name="ALL_TRADES"
max-rows="500"
></grid-pro-server-side-datasource>
</grid-pro>
`
})
export class ServerSideGridExample extends GenesisElement {
// Server-side datasource: loadMore automatically disabled
@observable serverStatusBarConfig: GridProStatusBarConfig = {
rows: true, // Available - shows row counts
maxRows: true, // Available - shows max rows info
loadMore: true, // DISABLED - even if true, will not show (by design when it is a server-side datasource)
reload: { // Available - shows reload button
tooltip: 'Refresh trade data from server'
},
aggregation: true // Available - shows aggregation values
};
}
3. Grid Pro with local data (no datasource component) and custom components
@customElement({
name: 'manual-data-grid',
template: html`
<grid-pro
:rowData="${(x) => x.rowData}"
:gridComponents="${(x) => x.gridComponents}"
:eventsAndCallbacks="${(x) => x.eventsAndCallbacks}"
theme="balham"
header-height="50"
persist-column-state-key="manual-grid-state"
enable-cell-flashing>
</grid-pro>
`
})
export class ManualDataGrid extends GenesisElement {
@observable rowData = [
{ id: 1, name: 'John Doe', age: 30, department: 'Engineering' },
{ id: 2, name: 'Jane Smith', age: 25, department: 'Marketing' },
// ... more data
];
@observable gridComponents = {
customRenderer: CustomCellRenderer,
customEditor: CustomCellEditor,
customFilter: CustomFilter
};
@observable eventsAndCallbacks = {
onCellValueChanged: (event) => {
console.log('Cell value changed:', event);
// Handle cell value changes
},
onRowSelected: (event) => {
console.log('Row selected:', event);
// Handle row selection
},
onGridReady: (event) => {
console.log('Grid ready:', event);
// Grid initialization complete
}
};
}
4. Theme and font customization
@customElement({
name: 'themed-grid',
template: html`
<grid-pro
theme="material"
:gridFontFace="${(x) => x.customFontFace}"
header-height="48"
row-height="42"
header-case-type="sentenceCase">
<grid-pro-server-side-datasource
resource-name="ALL_POSITIONS"
></grid-pro-server-side-datasource>
</grid-pro>
`
})
export class ThemedGrid extends GenesisElement {
@observable customFontFace = `
@font-face {
font-family: 'CustomGridFont';
src: url('path/to/custom-font.woff2') format('woff2');
}
`;
}
Supported row models
We support all the AG's Row Models. More on JavaScript Grid: Row Models | AG Grid (ag-grid.com).
In the table below you can find a complete feature list of all the possibilities of client/server-side row models (and others that can be manually enabled/integrated - but we don't expose any components for those yet).
It's important to note that any client app can implement the other Row Models to their own needs. Our Grid Pro component is not tied to the datasource. Datasources can be as specialized or customized as you want.
Infinite
and Viewport
row models are also supported, but not offered "out of the box". You will have to create your own component if you want to use these.
Feature | Client-Side | Server-Side | Notes |
---|---|---|---|
All Data in Client | ✓ | ✗ | Free |
Fetch Data as User Scrolls | ✗ | ✓ | Free |
Row Sorting | (client) | (client OR server) our component is server-only | Free |
Row Filtering | (client) | (client OR server) our component is server-only | Free |
Quick Filter | ✓ | ✓ | Free |
Floating Filters | ✓ | ✓ | Free |
Dynamic Row Height | ✓ | ✓ | Free |
Row Grouping | (client) | (server) | Paid (Enterprise) |
Row Pivoting | (client) | (server) | Paid (Enterprise) |
Lazy Loading Row Groups | ✗ | ✓ | Paid (Enterprise) |
Value Aggregation | (client) | (server) | Paid (Enterprise) |
Row Selection | ✓ | ✓ | Free |
Specify Selectable Rows | ✓ | ✓ | Free |
Header Checkbox Selection | ✓ | ✓ | Free |
Range Selection | ✓ | ✓ | Free |
Column Spanning | ✓ | ✓ | Free |
Column Pinning | ✓ | ✓ | Free |
Row Pinning | ✓ | ✓ | Free |
Pagination | ✓ | ✓ | Free |
Custom Filters | ✓ | ✓ | Free |
Cell Editors | ✓ | ✓ | Free |
Cell Renderers | ✓ | ✓ | Free |
Value Getter | ✓ | ✓ | Free |
Value Setter | ✓ | ✓ | Free |
Value Formatter | ✓ | ✓ | Free |
Value Parser | ✓ | ✓ | Free |
Full Width Rows | ✓ | ✓ | Free |
CSV Export | ✓ | (data on screen) | Free |
Excel Export | ✓ | (data on screen) | Paid (Enterprise) |
Clipboard Copy & Paste | ✓ | ✓ | Free |
Update via Transaction | ✓ | ✓ | Free |
Update via Async Transactions | ✓ | ✓ | Free |
Performance
DOM virtualisation
DOM Virtualisation is a powerful technique that enhances the performance of grid components by only rendering the rows and columns that are currently visible in the viewport. This approach significantly reduces the memory footprint and improves the rendering speed, enabling all of our "grid components" to handle larger datasets more efficiently.
- How It Works: Instead of rendering all rows and columns, the grid dynamically generates the DOM elements for only the visible part of the dataset. As the user scrolls, rows and columns are created or destroyed on the fly, ensuring a smooth scrolling experience.
- Benefits:
- Reduced memory usage since only a subset of rows and columns are in the DOM at any given time.
- Faster initial rendering and improved responsiveness, even with large datasets.
- Enhanced user experience with seamless scrolling and interaction.
For more details, visit the AG Grid DOM Virtualisation documentation (also available in Tabulator Virtual DOM)
Pagination
Pagination is another effective technique to improve performance in AG Grid by breaking down large datasets into smaller, manageable chunks or pages. This allows the grid to load and render only a subset of data at a time, significantly reducing the load on the client.
- How It Works: Data is divided into pages, and only the data for the current page is loaded and rendered. Users can navigate through pages using pagination controls.
- Benefits:
- Minimizes the amount of data loaded into the client at any given time, enhancing performance.
- Provides a structured way to navigate large datasets, improving usability.
- Reduces the risk of browser crashes and memory overflow issues.
Combined approach
By using both DOM Virtualisation and Pagination, our "grid components" can efficiently manage and display larger datasets on the client side. Here's how these techniques work together:
- Initial Load: Only the data for the first page is loaded, minimizing the initial load time.
- Scrolling: As users scroll, DOM Virtualisation ensures only the visible rows and columns are rendered, maintaining performance.
- Page Navigation: Users can navigate through pages to access the full dataset without overwhelming the client.
Legacy project set-up
This package is installed by default in applications build with Genesis Create or via the genx
CLI, but you can follow these steps to install it in your existing project.
Installation
To enable this module in your application, follow the steps below.
- Add
@genesislcap/grid-pro
as a dependency in yourpackage.json
file. Whenever you change the dependencies of your project, ensure you run the$ npm run bootstrap
command again. You can find more information in the package.json basics page.
{
"dependencies": {
"@genesislcap/grid-pro": "latest"
},
}
Set-up
Make sure the required grid components are registered with your design system. Depending on how the app was created this might have been setup for you automatically (genx cli / create). The design system name might vary (you can create a custom one for your app), using rapid in this example.
import { provideDesignSystem, baseComponents } from '@genesislcap/rapid-design-system';
import { rapidGridComponents } from '@genesislcap/rapid-grid-pro';
provideDesignSystem().register(baseComponents, rapidGridComponents);
If you're unsure where to register the component, search for the provideDesignSystem
method in your project.