Purpose
Use this skill to migrate a project from Grid Lite (igniteui-grid-lite, MIT licensed, <igc-grid-lite>) to the Premium Data Grid (igniteui-webcomponents-grids, commercially licensed, <igc-grid>). Grid Lite has read-only capabilities. Use this skill when the project needs enterprise features, for example editing, selection, paging, grouping, summaries, Excel export, or state persistence.
MANDATORY AGENT PROTOCOL
DO NOT write any code from memory. Grid APIs change between versions.
Before you write migration code:
- Identify the current Grid Lite usage - read the existing TypeScript and HTML files of the user. Find the column configuration, cell templates, data binding, and any
dataPipelineConfigurationusage. - Use the MCP server - when you are not sure about an API detail, call
mcp_igniteui-cli_get_api_referenceormcp_igniteui-cli_get_doc(framework:webcomponents) to verify it. - Only then produce output - write all code from verified references, not from memory.
When to Migrate
Migrate from Grid Lite to the Premium Grid when the user needs any of these features:
| Required Feature | Grid Lite | Premium Grid |
|---|---|---|
| Cell / Row / Batch editing | No | Yes |
| Row adding / deleting | No | Yes |
| Row / Cell / Column selection | No | Yes |
| Paging (client or remote) | No | Yes |
| GroupBy | No | Yes |
| Summaries (built-in & custom) | No | Yes |
| Column pinning | No | Yes |
| Column moving | No | Yes |
| Master-Detail rows | No | Yes |
| Export (Excel / CSV) | No | Yes |
| Toolbar | No | Yes |
| State persistence | No | Yes |
| Advanced filtering | No | Yes |
| Action strip | No | Yes |
| Row drag | No | Yes |
| Clipboard support | No | Yes |
| Cell merging | No | Yes |
IMPORTANT: The upgrade path from Grid Lite is always to
IgcGridComponent(<igc-grid>). Do not recommend a different component type as a substitute.
Step 1 - Install / Verify the Premium Package
Grid Lite uses the separate igniteui-grid-lite npm package. The Premium Grid is in the igniteui-webcomponents-grids package (or @infragistics/igniteui-webcomponents-grids for licensed builds).
AGENT INSTRUCTION: Check
package.jsonto find which package variant is installed. If onlyigniteui-grid-liteis present, the user must install the premium package.
# Remove Grid Lite
npm uninstall igniteui-grid-lite
# Open-source / trial (shows watermark)
npm install igniteui-webcomponents-grids
# OR licensed package (requires private registry)
npm install @infragistics/igniteui-webcomponents-grids
Step 2 - Update Imports and Registration
Before (Grid Lite):
import { IgcGridLite, IgcGridLiteColumn } from 'igniteui-grid-lite';
import type { BaseIgcCellContext } from 'igniteui-grid-lite';
import 'igniteui-webcomponents/themes/light/bootstrap.css';
After (Premium Grid):
// Side-effect import - registers all premium grid custom elements; must come first
import 'igniteui-webcomponents-grids/grids/combined.js';
// Type imports
import type {
IgcGridComponent,
IgcColumnComponent,
IgcCellTemplateContext,
IgcColumnTemplateContext,
IgcSortingEventArgs,
IgcFilteringEventArgs,
IgcRowSelectionEventArgs,
IgcSortingExpression,
} from 'igniteui-webcomponents-grids';
// Value imports
import {
SortingDirection,
IgcStringFilteringOperand,
IgcNumberFilteringOperand,
IgcBooleanFilteringOperand,
IgcDateFilteringOperand,
IgcFilteringExpressionsTree,
FilteringLogic,
IgcNoopSortingStrategy,
IgcNoopFilteringStrategy,
} from 'igniteui-webcomponents-grids';
// Theme — import as an inline string so it can be injected into the shadow root (requires bundler support for ?inline, e.g. Vite)
// Available: light|dark x bootstrap|material|fluent|indigo
import gridTheme from 'igniteui-webcomponents-grids/grids/themes/light/material.css?inline';
Grid inside a Shadow root — required step: A bare CSS import goes into the document head. It does not go into a Shadow root, so the internal structure and elements of the grid get no styles. Inject the theme as a
<style>tag inside the shadow root. For a LitElement component, put the tag at the top ofrender():render() { return html` <style>${gridTheme}</style> <igc-grid ...></igc-grid> `; }
Step 3 - Update HTML Tags
| Grid Lite | Premium Grid |
|---|---|
<igc-grid-lite> |
<igc-grid> |
<igc-grid-lite-column> |
<igc-column> |
Bare boolean attrs (sortable, filterable, hidden) |
Quoted values (sortable="true", filterable="true", hidden="true") |
| No grid-level filter toggle | allow-filtering="true" required on <igc-grid> |
| No height requirement | height attribute required for row virtualization |
Before:
<igc-grid-lite id="grid" auto-generate>
<igc-grid-lite-column field="name" sortable filterable resizable></igc-grid-lite-column>
<igc-grid-lite-column field="price" data-type="number" sortable></igc-grid-lite-column>
</igc-grid-lite>
After:
<!-- height is required for row virtualization; set it here or on a fixed-height parent -->
<igc-grid id="grid" auto-generate="true" allow-filtering="true" height="600px">
<igc-column field="name" sortable="true" filterable="true" resizable="true"></igc-column>
<igc-column field="price" data-type="number" sortable="true"></igc-column>
</igc-grid>
Note: To enable filtering, set
allow-filtering="true"on<igc-grid>. Grid Lite has no grid-level filter toggle.
Step 4 - Update TypeScript References
// Before
const grid = document.getElementById('grid') as IgcGridLite;
const column = document.querySelector('igc-grid-lite-column[field="name"]') as IgcGridLiteColumn;
// After
const grid = document.getElementById('grid') as IgcGridComponent;
const column = document.querySelector('igc-column[field="name"]') as IgcColumnComponent;
// grid.data = myArray - unchanged
Step 5 - Migrate Column Properties
| Grid Lite Property | Premium Grid Property | Notes |
|---|---|---|
field |
field |
Unchanged |
header |
header |
Unchanged |
width |
width |
Unchanged |
hidden |
hidden |
Unchanged |
resizable |
resizable |
Unchanged |
sortable |
sortable |
Unchanged |
filterable |
filterable |
Unchanged |
dataType |
dataType |
Premium adds dateTime, time, currency, percent |
filteringCaseSensitive |
filteringIgnoreCase |
Logic inverted - true becomes false |
sortingCaseSensitive |
sortingIgnoreCase |
Logic inverted - true becomes false |
sortConfiguration: { comparer } |
sortStrategy |
Object with a sort(...) method (see below) - no base class to extend |
| (none) | editable, pinned, groupable, hasSummary, disableHiding, disablePinning, selectable, searchable, formatter, minWidth, maxWidth |
Premium-only |
Custom sort strategy migration:
The Premium Grid does not export a base class for sort strategies. It exports IgcSortingStrategy
as a type only, and the built-in default strategy is internal. A column's sortStrategy can be any object that has this method:
sort(data: any[], fieldName: string, dir: SortingDirection, ignoreCase: boolean,
valueResolver: (record: any, fieldName: string, isDate?: boolean, isTime?: boolean) => any): any[]
The method receives the full data array and returns it sorted. Read cell values through
valueResolver, not through record[fieldName]. This makes sure that nested fields (for example,
address.city) and date/time columns work.
// Before (Grid Lite) - function comparer on column
column.sortConfiguration = { comparer: (a, b) => a.length - b.length };
// After (Premium Grid) - object implementing sort()
import { SortingDirection } from 'igniteui-webcomponents-grids';
class LengthSort {
sort(data: any[], fieldName: string, dir: SortingDirection, _ignoreCase: boolean,
valueResolver: (record: any, fieldName: string, isDate?: boolean, isTime?: boolean) => any) {
const factor = dir === SortingDirection.Desc ? -1 : 1;
const len = (record: any) => String(valueResolver(record, fieldName) ?? '').length;
return [...data].sort((a, b) => factor * (len(a) - len(b)));
}
}
column.sortStrategy = new LengthSort();
Step 6 - Migrate Cell and Header Templates
| Aspect | Grid Lite | Premium Grid |
|---|---|---|
| Cell template property | column.cellTemplate |
column.bodyTemplate |
| Cell context type | BaseIgcCellContext |
IgcCellTemplateContext |
| Cell value | ctx.value |
ctx.implicit |
| Row data | ctx.row |
ctx.cell.row.data |
| Header template | no params | IgcColumnTemplateContext param |
Cell template migration:
// Before (Grid Lite)
column.cellTemplate = (ctx) => html`<span class=${ctx.value}>${ctx.value}</span>`;
// After (Premium Grid)
column.bodyTemplate = (ctx: IgcCellTemplateContext) =>
html`<span class=${ctx.implicit}>${ctx.implicit}</span>`;
Header template migration:
// Before (Grid Lite) - no parameters
column.headerTemplate = () => html`<strong>Name</strong>`;
// After (Premium Grid) - receives IgcColumnTemplateContext
column.headerTemplate = (ctx: IgcColumnTemplateContext) =>
html`<strong>${ctx.column.header ?? ctx.column.field}</strong>`;
Step 7 - Migrate Remote Data Operations
Grid Lite uses dataPipelineConfiguration (async callbacks). The Premium Grid uses noop strategies + events.
Before (Grid Lite):
grid.dataPipelineConfiguration = {
sort: async ({ grid }) => dataService.sortRemote(grid.sortingExpressions),
filter: async ({ grid }) => dataService.filterRemote(grid.filterExpressions),
};
After (Premium Grid):
const grid = document.getElementById('grid') as IgcGridComponent;
// Disable built-in sort/filter so the grid does not process data locally
grid.sortStrategy = IgcNoopSortingStrategy.instance();
grid.filterStrategy = IgcNoopFilteringStrategy.instance();
// React to done events and reload data from the server
grid.addEventListener('sortingDone', async () => {
grid.data = await dataService.sortRemote(grid.sortingExpressions);
});
grid.addEventListener('filteringDone', async () => {
grid.data = await dataService.filterRemote(grid.filteringExpressionsTree);
});
Step 8 - Migrate Sort / Filter Events
| Grid Lite Event | Premium Grid Event | Notes |
|---|---|---|
sorting |
sorting |
Same name - both cancellable (e.detail.cancel = true) |
sorted |
sortingDone |
Name changed - CustomEvent<IgcSortingExpression[]> |
filtering |
filtering |
Same name - both cancellable |
filtered |
filteringDone |
Name changed - CustomEvent<IgcFilteringExpressionsTree> |
// Cancel a sort before it applies
grid.addEventListener('sorting', (e: CustomEvent<IgcSortingEventArgs>) => {
e.detail.cancel = true;
});
// React after sort completes
grid.addEventListener('sortingDone', (e: CustomEvent<IgcSortingExpression[]>) => {
console.log('Sorted by', e.detail);
});
// Cancel a filter before it applies
grid.addEventListener('filtering', (e: CustomEvent<IgcFilteringEventArgs>) => {
e.detail.cancel = true;
});
// React after filter completes
grid.addEventListener('filteringDone', (e: CustomEvent<IgcFilteringExpressionsTree>) => {
console.log('Filter tree', e.detail);
});
Step 9 - Migrate Programmatic Sort / Filter API
Grid Lite API:
grid.sort({ key: 'name', direction: 'ascending' });
grid.filter({ key: 'age', condition: 'greaterThan', searchTerm: 21 });
grid.clearSort();
grid.clearFilter();
Premium Grid API:
import { SortingDirection, IgcNumberFilteringOperand } from 'igniteui-webcomponents-grids';
// Sorting - fieldName + SortingDirection enum (Asc = 1, Desc = 2, None = 0)
grid.sort([{ fieldName: 'name', dir: SortingDirection.Asc, ignoreCase: true }]);
grid.clearSort('name'); // clear one column
grid.clearSort(); // clear all
// Filtering - positional arguments with typed operand instances
grid.filter('age', 21, IgcNumberFilteringOperand.instance().condition('greaterThan'), true);
grid.clearFilter('age'); // clear one column
grid.clearFilter(); // clear all
// Multi-column filtering via expression tree
const tree = new IgcFilteringExpressionsTree(FilteringLogic.And);
tree.filteringOperands.push({
fieldName: 'age',
condition: IgcNumberFilteringOperand.instance().condition('greaterThan'),
searchVal: 21,
ignoreCase: true,
});
grid.filteringExpressionsTree = tree;
Key expression shape changes:
| Aspect | Grid Lite | Premium Grid |
|---|---|---|
| Sort target field | key |
fieldName |
| Sort direction | direction: 'ascending' (string) |
dir: SortingDirection.Asc (enum) |
| Filter target field | key |
fieldName |
| Filter search value | searchTerm |
searchVal (expression tree) |
| Case sensitivity (sort) | caseSensitive: true |
ignoreCase: false (inverted) |
| Case sensitivity (filter) | caseSensitive: true |
ignoreCase: false (inverted) |
| Filter criteria | criteria string |
FilteringLogic enum on the tree |
Adding Enterprise Features Post-Migration
After you migrate to the Premium Grid, enable the features that were the reason for the migration:
Row Editing
<igc-grid id="grid" row-editable="true" primary-key="id" height="600px">
<igc-column field="name" editable="true"></igc-column>
<igc-column field="price" data-type="number" editable="true"></igc-column>
</igc-grid>
Note: We strongly recommend that you set
primary-keywhen you use editing, selection, or row-targeted APIs (getRowByKey, row pinning, transactions). Without it, the grid uses object identity. Object identity breaks across virtualization and remote data.
Row Selection
<igc-grid id="grid" row-selection="multiple" primary-key="id" height="600px">
<!-- columns -->
</igc-grid>
grid.addEventListener('rowSelectionChanging', (e: CustomEvent<IgcRowSelectionEventArgs>) => {
console.log('Selected rows:', e.detail.added);
});
Paging
<igc-grid id="grid" primary-key="id" height="600px">
<!-- columns -->
<igc-paginator per-page="15"></igc-paginator>
</igc-grid>
GroupBy
<igc-grid id="grid" primary-key="id" height="600px">
<igc-column field="category" groupable="true"></igc-column>
</igc-grid>
grid.groupBy([{ fieldName: 'category', dir: SortingDirection.Asc }]);
Column Pinning
const column = grid.getColumnByName('name');
column.pin(); // pin to start (default)
column.unpin();
Summaries
<igc-column field="price" data-type="number" has-summary="true"></igc-column>
Toolbar (Column Hiding, Pinning, Export)
<igc-grid id="grid" auto-generate="true" height="600px">
<igc-grid-toolbar>
<igc-grid-toolbar-title>My Grid</igc-grid-toolbar-title>
<igc-grid-toolbar-actions>
<igc-grid-toolbar-advanced-filtering></igc-grid-toolbar-advanced-filtering>
<igc-grid-toolbar-hiding></igc-grid-toolbar-hiding>
<igc-grid-toolbar-pinning></igc-grid-toolbar-pinning>
<igc-grid-toolbar-exporter></igc-grid-toolbar-exporter>
</igc-grid-toolbar-actions>
</igc-grid-toolbar>
<!-- columns -->
</igc-grid>
Advanced Filtering Dialog
grid.allowAdvancedFiltering = true;
grid.openAdvancedFilteringDialog();
Excel-Style Filter UI
grid.filterMode = 'excelStyleFilter'; // default is 'quickFilter'
Batch Editing
<igc-grid id="grid" batch-editing="true" row-editable="true" primary-key="id" height="600px">
<igc-column field="name" editable="true"></igc-column>
</igc-grid>
Related Skills
igniteui-wc-integrate-with-framework- Framework integration setupigniteui-wc-customize-component-theme- Theming and stylingigniteui-wc-choose-components- Choosing the right grid component