Plugin Overview
Understand ZenGrid's plugin architecture, lifecycle phases, and dependency system.
ZenGrid’s plugin architecture provides a modular, extensible system for adding functionality to the grid. Plugins follow a structured lifecycle with phase-based initialization and dependency management.
Plugin Interface
Every ZenGrid plugin implements the GridPlugin interface:
interface GridPlugin { name: string; phase: number; dependencies?: string[]; setup(store: GridStore, api: GridApi, context: GridPluginSetupContext): PluginDisposable | void; dispose?(): void;}The setup method receives the reactive store, the grid API, and a live plugin context for reading and subscribing to runtime option changes.
Lifecycle Phases
Plugins are initialized in phase order (0-130), ensuring dependencies load before dependent plugins:
CorePlugin // Phase 0SortPlugin // Phase 10FilterPlugin // Phase 20SelectionPlugin // Phase 40EditingPlugin // Phase 45UndoRedoPlugin // Phase 50ScrollPlugin // Phase 100ViewportPlugin // Phase 110ResizePlugin // Phase 120InfiniteScrollPlugin // Phase 130Choose a phase number higher than your dependencies to ensure proper initialization order.
Dependency System
Plugins can declare dependencies on other plugins:
const myPlugin: GridPlugin = { name: 'MyPlugin', phase: 60, dependencies: ['CorePlugin', 'SelectionPlugin'], setup(store, api, context) { // CorePlugin and SelectionPlugin are guaranteed to be initialized return { teardown: [] }; }};PluginHost
The PluginHost manages plugin registration and lifecycle:
// Register a plugingrid.usePlugin(plugin);
// Plugin managementpluginHost.has('PluginName');pluginHost.getPluginNames();pluginHost.getPluginsByPhase(10);
// Cleanup all pluginspluginHost.destroy();Plugin Setup
The setup method receives three key objects:
- GridStore: Reactive state management system
- GridApi: Grid operations and methods
- GridPluginSetupContext: Live access to current options plus change subscriptions
setup(store: GridStore, api: GridApi, context: GridPluginSetupContext) { // Create reactive state store.extend('myFeature.enabled', true, 'MyPlugin', this.phase);
const unsubscribeOptions = context.subscribeOptions((change) => { if (change.changedKeys.includes('rowHeight')) { api.fireEvent('myFeature:rowHeightChanged', { rowHeight: change.currentOptions.rowHeight, }); } });
// Create computed values store.computed('myFeature.status', () => { return store.get('myFeature.enabled') ? 'active' : 'inactive'; }, 'MyPlugin', this.phase);
// Register API methods api.register('myFeature', { enable: () => store.set('myFeature.enabled', true), disable: () => store.set('myFeature.enabled', false) });
return { teardown: [unsubscribeOptions] };}Plugin Disposable
Plugins return a PluginDisposable from setup for cleanup:
interface PluginDisposable { teardown: Array<() => void>;}Always add cleanup functions to the teardown array to prevent memory leaks.
Built-in Plugins
ZenGrid includes these built-in plugins:
| Plugin | Phase | Purpose |
|---|---|---|
| CorePlugin | 0 | Foundational data and state management |
| SortPlugin | 10 | Sorting integration with reactive store |
| FilterPlugin | 20 | Filtering with backend adapters |
| SelectionPlugin | 40 | Selection with IntervalTree queries |
| EditingPlugin | 45 | Cell editing lifecycle management |
| UndoRedoPlugin | 50 | Command pattern undo/redo system |
| ScrollPlugin | 100 | Scroll state management |
| ViewportPlugin | 110 | Virtual scrolling viewport |
| ResizePlugin | 120 | Column and row resizing |
| InfiniteScrollPlugin | 130 | Infinite scroll data loading |
Registering Plugins
Use grid.usePlugin() to register plugins:
import { createGrid, createSortPlugin, createFilterPlugin } from '@zengrid/core';
const grid = createGrid(container, options);
// Register built-in pluginsgrid.usePlugin(createSortPlugin());grid.usePlugin(createFilterPlugin());
// Register custom pluginsgrid.usePlugin(myCustomPlugin);Plugins are initialized immediately upon registration, respecting phase order and dependencies.