From 661f9686fff3d5c4db8bca2dce348a5ffaa8af83 Mon Sep 17 00:00:00 2001 From: Ivan Minchev Date: Thu, 4 Sep 2025 09:24:04 +0300 Subject: [PATCH 1/4] feat(cell-merging): add cell merging topic --- .../components/grids/_shared/cell-merging.md | 170 ++++++++++++++++++ docfx/en/components/toc.json | 22 ++- 2 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 doc/en/components/grids/_shared/cell-merging.md diff --git a/doc/en/components/grids/_shared/cell-merging.md b/doc/en/components/grids/_shared/cell-merging.md new file mode 100644 index 000000000..e97f70c51 --- /dev/null +++ b/doc/en/components/grids/_shared/cell-merging.md @@ -0,0 +1,170 @@ +--- +title: {Platform} {ComponentTitle} Cell Merging - {ProductName} +_description: Position and size columns in a more powerful way, using the multi-row layout functionality in the {ProductName} for {Platform} {ComponentTitle}. Check out examples and demos! +_keywords: cell merging, {Platform}, {ComponentKeywords}, {ProductName}, Infragistics +mentionedTypes: [{ComponentApiMembers}] +sharedComponents: ["Grid", "TreeGrid", "HierarchicalGrid"] +namespace: Infragistics.Controls +_canonicalLink: {CanonicalLinkToGridCellMerging} +--- + +# {Platform} {ComponentTitle} Cell Merging + +The Ignite UI for {Platform} {ComponentTitle} provides a Cell Merging feature that combines two or more adjacent cells with the same value into a single, larger cell. Merging is applied vertically within a column and helps improve readability by reducing duplicate values. The feature can be configured to merge cells either by default matching data values or by applying a custom condition. + +## {Platform} {ComponentTitle} Cell Merging Example + +`sample="/{ComponentSample}/cell-merging", height="700", alt="{Platform} {ComponentTitle} Cell Merging Example"` + +## Enabling and Using Cell Merging +Cell merging in the grid is controlled at two levels: + - Grid-level merge mode – determines when merging is applied. + - Column-level merge toggle – determines which columns can merge cells. + +### Grid Merge Mode +The grid exposes a `cellMergeMode` property that accepts values from the `GridCellMergeMode` enum: + - `always` - Merges any adjacent cells that meet the merging condition, regardless of sort state. + - `onSort` - Merges adjacent cells only when the column is sorted **(default value)**. + +```html +<@@igSelector [data]="data" [cellMergeMode]="cellMergeMode"> + ... + +``` +```ts +protected cellMergeMode: GridCellMergeMode = 'always'; +``` + +### Column Merge Toggle +At the column level, merging can be enabled or disabled with the `merge` property. + +```html + + +``` + +In the above example: + - The **OrderID** column will merge adjacent duplicate values. + - The **ShipperName** column will render normally without merging. + +### Combined Example + +```html +<@@igSelector [data]="data" [cellMergeMode]="cellMergeMode" [autoGenerate]="false"> + + + + +``` +```ts +protected cellMergeMode: GridCellMergeMode = 'onSort'; +``` +Here, the grid is set to merge only when columns are sorted, and both Category and Product columns are configured for merging. + +## Custom Merge Conditions +In addition to the built-in `always` and `onSort` modes, the grid allows you to define a custom condition for merging cells through the `mergeStrategy` property. This strategy controls both how cells are compared and how merged ranges are calculated. + +### Merge Strategy Interface +A custom merge strategy must implement the `IGridMergeStrategy` interface: + +```ts +export interface IGridMergeStrategy { + merge: ( + data: any[], + field: string, + comparer: (prevRecord: any, currentRecord: any, field: string) => boolean, + result: any[], + activeRowIndex?: number, + grid?: GridType + ) => any[]; + + comparer: (prevRecord: any, record: any, field: string) => boolean; +} +``` +- `merge` - defines how merged cells are produced. +- `comparer` - defines the condition to decide if two adjacent records should be merged. + + +### Extending the Default Strategy + +If you only want to customize part of the behavior (for example, the comparer logic), you can extend the built-in `DefaultMergeStrategy` and override the relevant methods. + +```ts +export class MyCustomStrategy extends DefaultMergeStrategy { + /* Merge only cells within their respective projects */ + public override comparer(prevRecord: any, record: any, field: string): boolean { + const a = prevRecord[field]; + const b = record[field]; + const projA = prevRecord['ProjectName']; + const projB = record['ProjectName']; + return a === b && projA === projB; + } +} +``` + + +The `IgxTreeGrid` provides two built-in strategies that implement the `IGridMergeStrategy` interface: `DefaultTreeGridMergeStrategy` and `ByLevelTreeGridMergeStrategy`. `DefaultTreeGridMergeStrategy` merges all cells with the same value, regardless of their hierarchical level. In contrast, `ByLevelTreeGridMergeStrategy` only merges cells if they have the same value and are located at the same level, making level a required condition for merging. + +### Extending the Default Strategy + +If you only want to customize part of the behavior (for example, the comparer logic), you can extend one of the built-in strategies, either `DefaultTreeGridMergeStrategy` or `ByLevelTreeGridMergeStrategy`, and override the relevant methods. + +```ts +export class MyCustomStrategy extends DefaultTreeGridMergeStrategy { + /* Merge only cells within their respective projects */ + public override comparer(prevRecord: any, record: any, field: string): boolean { + const a = prevRecord[field]; + const b = record[field]; + const projA = prevRecord['ProjectName']; + const projB = record['ProjectName']; + return a === b && projA === projB; + } +} +``` + + +### Applying a Custom Strategy +Once defined, assign the strategy to the grid through the `mergeStrategy` property: +```html +<@@igSelector [data]="data" [mergeStrategy]="customStrategy"> + + + +``` +```ts +protected customStrategy = new MyCustomStrategy(); +``` + +### Demo +`sample="/{ComponentSample}/cell-merging-custom", height="700", alt="{Platform} {ComponentTitle} Cell Merging Example"` + + +## Feature Integration +Due to the specific behavior of merged cells it has to be noted how exactly it ties together with some of the other features of the grid: + +- **Expand/Collapse**: if a feature (such as master-detail, grouping, etc.) generates a non-data row, then the cell merging is interrupted and the group will be split. + +- **Excel export**: merged cells remain merged when exported to Excel. +- **Column pinning**: cells remain merged when a column is pinned and are displayed in the pinned area. +- **Row pinning**: cells merge only withing their containing area, i.e. cells of pinned rows merge only with cells of other pinned rows, while cells of unpinned rows merge only with cells of unpinned rows. +- **Navigation/Activation**: when a cell is active, all merged cells in the same row become single cells, i.e. their merge sequence is broken. This also includes activation via keyboard navigation. + +>[!NOTE] +> If a merged cell is clicked, the closest cell from the merge sequence will become active. + +- **Updating/Editing**: since activation breaks the merge sequence, only a single cell will be in edit mode. +- **Row selection**: if selected rows intersect merged cells, all related merged cells should be marked as part of the selection. + + +## Limitations +|Known Limitations| Description| +| --- | --- | +| Cell merging is not supported in combination with Multi-row Layout. | Both span complex layouts that don't make sense when combined. A warning will be thrown if such invalid configuration is detected. | + + +## API References +* `{ComponentName}` + +## Additional Resources + \ No newline at end of file diff --git a/docfx/en/components/toc.json b/docfx/en/components/toc.json index c775c0c66..f53f45fac 100644 --- a/docfx/en/components/toc.json +++ b/docfx/en/components/toc.json @@ -158,6 +158,12 @@ "name": "Grid", "href": "grids/data-grid.md", "items": [ + { + "exclude": ["Angular"], + "name": "Cell Merging", + "href": "grids/grid/cell-merging.md", + "status": "NEW" + }, { "exclude": ["Angular"], "name": "Clipboard Interactions", @@ -396,6 +402,12 @@ "name": "Hierarchical Grid", "href": "grids/hierarchical-grid/overview.md", "items": [ + { + "exclude": ["Angular"], + "name": "Cell Merging", + "href": "grids/hierarchical-grid/cell-merging.md", + "status": "NEW" + }, { "exclude": ["Angular"], "name": "Collapsible Column Groups", @@ -618,6 +630,12 @@ "name": "Tree Grid", "href": "grids/tree-grid/overview.md", "items": [ + { + "exclude": ["Angular"], + "name": "Cell Merging", + "href": "grids/tree-grid/cell-merging.md", + "status": "NEW" + }, { "exclude": ["Angular"], "name": "Clipboard Interactions", @@ -900,10 +918,6 @@ "href": "grids/data-grid/cell-editing.md", "status": "" }, - { - "name": "Cell Merging", - "href": "grids/data-grid/cell-merging.md" - }, { "name": "Cell Selection", "href": "grids/data-grid/cell-selection.md", From b33fe96f9135f9ac6e9b7fc2232967d42537e436 Mon Sep 17 00:00:00 2001 From: Ivan Minchev Date: Tue, 14 Oct 2025 11:13:58 +0300 Subject: [PATCH 2/4] chore(cell-merging): add additional resources --- doc/en/components/grids/_shared/cell-merging.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/en/components/grids/_shared/cell-merging.md b/doc/en/components/grids/_shared/cell-merging.md index e97f70c51..67ab346b3 100644 --- a/doc/en/components/grids/_shared/cell-merging.md +++ b/doc/en/components/grids/_shared/cell-merging.md @@ -166,5 +166,13 @@ Due to the specific behavior of merged cells it has to be noted how exactly it t * `{ComponentName}` ## Additional Resources - \ No newline at end of file + +* [Ignite UI for React](../components/general-getting-started.md) +* [{ComponentName} Overview](../components/grids/data-grid.md) + + +* [{ComponentName} Overview](overview.md) + + +* [{ComponentName} Overview](overview.md) + From 3c58f5ee51f87f0cfb2b33d0fa9545027526afa8 Mon Sep 17 00:00:00 2001 From: Ivan Minchev Date: Wed, 22 Oct 2025 13:34:01 +0300 Subject: [PATCH 3/4] feat(cell-merging): add code snippets for React --- .../components/grids/_shared/cell-merging.md | 84 ++++++++++--------- docfx/en/components/toc.json | 6 +- 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/doc/en/components/grids/_shared/cell-merging.md b/doc/en/components/grids/_shared/cell-merging.md index 67ab346b3..a1886f4a7 100644 --- a/doc/en/components/grids/_shared/cell-merging.md +++ b/doc/en/components/grids/_shared/cell-merging.md @@ -26,21 +26,20 @@ The grid exposes a `cellMergeMode` property that accepts values from the `GridCe - `always` - Merges any adjacent cells that meet the merging condition, regardless of sort state. - `onSort` - Merges adjacent cells only when the column is sorted **(default value)**. -```html -<@@igSelector [data]="data" [cellMergeMode]="cellMergeMode"> +```tsx +<{ComponentSelector} data={data} cellMergeMode={cellMergeMode} > ... - + ``` -```ts -protected cellMergeMode: GridCellMergeMode = 'always'; +```tsx +const cellMergeMode: GridCellMergeMode = 'always'; ``` - ### Column Merge Toggle At the column level, merging can be enabled or disabled with the `merge` property. -```html - - +```tsx + + ``` In the above example: @@ -49,26 +48,26 @@ In the above example: ### Combined Example -```html -<@@igSelector [data]="data" [cellMergeMode]="cellMergeMode" [autoGenerate]="false"> - - - - +```tsx +<{ComponentSelector} data={data} cellMergeMode]={cellMergeMode} autoGenerate={false}> + + + + ``` -```ts -protected cellMergeMode: GridCellMergeMode = 'onSort'; +```tsx +const cellMergeMode: GridCellMergeMode = 'onSort'; ``` Here, the grid is set to merge only when columns are sorted, and both Category and Product columns are configured for merging. ## Custom Merge Conditions In addition to the built-in `always` and `onSort` modes, the grid allows you to define a custom condition for merging cells through the `mergeStrategy` property. This strategy controls both how cells are compared and how merged ranges are calculated. -### Merge Strategy Interface -A custom merge strategy must implement the `IGridMergeStrategy` interface: +### Merge Strategy Class +A custom merge strategy must implement the `IgrGridMergeStrategy` class: ```ts -export interface IGridMergeStrategy { +export declare class IgrGridMergeStrategy { merge: ( data: any[], field: string, @@ -87,10 +86,10 @@ export interface IGridMergeStrategy { ### Extending the Default Strategy -If you only want to customize part of the behavior (for example, the comparer logic), you can extend the built-in `DefaultMergeStrategy` and override the relevant methods. +If you only want to customize part of the behavior (for example, the comparer logic), you can extend the built-in `IgrDefaultMergeStrategy` and override the relevant methods. ```ts -export class MyCustomStrategy extends DefaultMergeStrategy { +export class MyCustomStrategy extends IgrDefaultMergeStrategy { /* Merge only cells within their respective projects */ public override comparer(prevRecord: any, record: any, field: string): boolean { const a = prevRecord[field]; @@ -110,7 +109,7 @@ The `IgxTreeGrid` provides two built-in strategies that implement the `IGridMerg If you only want to customize part of the behavior (for example, the comparer logic), you can extend one of the built-in strategies, either `DefaultTreeGridMergeStrategy` or `ByLevelTreeGridMergeStrategy`, and override the relevant methods. ```ts -export class MyCustomStrategy extends DefaultTreeGridMergeStrategy { +export class MyCustomStrategy extends IgrDefaultTreeGridMergeStrategy { /* Merge only cells within their respective projects */ public override comparer(prevRecord: any, record: any, field: string): boolean { const a = prevRecord[field]; @@ -125,18 +124,18 @@ export class MyCustomStrategy extends DefaultTreeGridMergeStrategy { ### Applying a Custom Strategy Once defined, assign the strategy to the grid through the `mergeStrategy` property: -```html -<@@igSelector [data]="data" [mergeStrategy]="customStrategy"> - - - +```tsx +<{ComponentSelector} data={data} mergeStrategy={customStrategy}> + + + ``` ```ts -protected customStrategy = new MyCustomStrategy(); +const customStrategy = new MyCustomStrategy() as IgrGridMergeStrategy; ``` ### Demo -`sample="/{ComponentSample}/cell-merging-custom", height="700", alt="{Platform} {ComponentTitle} Cell Merging Example"` +`sample="/{ComponentSample}/cell-merge-custom-sample", height="700", alt="{Platform} {ComponentTitle} Cell Merging Example"` ## Feature Integration @@ -166,13 +165,18 @@ Due to the specific behavior of merged cells it has to be noted how exactly it t * `{ComponentName}` ## Additional Resources - -* [Ignite UI for React](../components/general-getting-started.md) -* [{ComponentName} Overview](../components/grids/data-grid.md) - - -* [{ComponentName} Overview](overview.md) - - -* [{ComponentName} Overview](overview.md) - +* [Filtering](filtering.md) +* [Excel Style Filtering](excel-style-filtering.md) +* [Virtualization and Performance](virtualization.md) +* [Paging](paging.md) +* [Sorting](sorting.md) +* [Summaries](summaries.md) +* [Column Moving](column-moving.md) +* [Column Pinning](column-pinning.md) +* [Column Resizing](column-resizing.md) +* [Selection](selection.md) + +Our community is active and always welcoming to new ideas. + +* [{ProductName} **Forums**]({ForumsLink}) +* [{ProductName} **GitHub**]({GithubLink}) diff --git a/docfx/en/components/toc.json b/docfx/en/components/toc.json index f53f45fac..a66a38bfc 100644 --- a/docfx/en/components/toc.json +++ b/docfx/en/components/toc.json @@ -159,7 +159,7 @@ "href": "grids/data-grid.md", "items": [ { - "exclude": ["Angular"], + "exclude": ["Angular", "WebComponents", "Blazor"], "name": "Cell Merging", "href": "grids/grid/cell-merging.md", "status": "NEW" @@ -403,7 +403,7 @@ "href": "grids/hierarchical-grid/overview.md", "items": [ { - "exclude": ["Angular"], + "exclude": ["Angular", "WebComponents", "Blazor"], "name": "Cell Merging", "href": "grids/hierarchical-grid/cell-merging.md", "status": "NEW" @@ -631,7 +631,7 @@ "href": "grids/tree-grid/overview.md", "items": [ { - "exclude": ["Angular"], + "exclude": ["Angular", "WebComponents", "Blazor"], "name": "Cell Merging", "href": "grids/tree-grid/cell-merging.md", "status": "NEW" From f5693367e496f1e11f2c9574f6ab21398abc519d Mon Sep 17 00:00:00 2001 From: Deyan Kamburov Date: Thu, 23 Oct 2025 15:32:48 +0300 Subject: [PATCH 4/4] chore(*): Change the url to match the sample in react --- doc/en/components/grids/_shared/cell-merging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/components/grids/_shared/cell-merging.md b/doc/en/components/grids/_shared/cell-merging.md index a1886f4a7..1d7e46a6c 100644 --- a/doc/en/components/grids/_shared/cell-merging.md +++ b/doc/en/components/grids/_shared/cell-merging.md @@ -14,7 +14,7 @@ The Ignite UI for {Platform} {ComponentTitle} provides a Cell Merging feature th ## {Platform} {ComponentTitle} Cell Merging Example -`sample="/{ComponentSample}/cell-merging", height="700", alt="{Platform} {ComponentTitle} Cell Merging Example"` +`sample="/{ComponentSample}/cell-merge", height="700", alt="{Platform} {ComponentTitle} Cell Merging Example"` ## Enabling and Using Cell Merging Cell merging in the grid is controlled at two levels: