Skip to content

Commit f433452

Browse files
authored
Merge pull request #1860 from telerik/new-kb-jan2024
docs(grid): add merge duplicate rows and cells data kb
2 parents 3956a51 + d741aa6 commit f433452

File tree

3 files changed

+256
-0
lines changed

3 files changed

+256
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React, { useState } from 'react';
2+
import ReactDOM from 'react-dom';
3+
import { Grid, GridColumn as Column } from '@progress/kendo-react-grid';
4+
import products from './products.json';
5+
6+
const App = () => {
7+
const [gridData, setGridData] = useState(products);
8+
const gridRef = React.useRef(null);
9+
const cellRender = (cell, props) => {
10+
const { dataItem, field } = props;
11+
let duplicate = false;
12+
if (gridRef.current) {
13+
const rowIndex = props.dataIndex;
14+
const columns = gridRef.current.columns;
15+
const colIndex = columns.findIndex((c) => c.field == props.field);
16+
17+
if (colIndex > 0) {
18+
if (
19+
dataItem[columns[colIndex].field] ==
20+
dataItem[columns[colIndex - 1].field]
21+
) {
22+
duplicate = true;
23+
}
24+
}
25+
if (rowIndex > 0) {
26+
if (
27+
dataItem[props.field] ==
28+
gridRef.current.props.data[rowIndex - 1][props.field]
29+
) {
30+
duplicate = true;
31+
}
32+
}
33+
}
34+
let style = { ...cell.props.style };
35+
if (typeof dataItem[props.field] == 'boolean') {
36+
style.backgroundColor = dataItem[props.field] ? '#1fb542' : '#b51f2e';
37+
style.color = dataItem[props.field] ? '#1fb542' : '#b51f2e';
38+
style.border = 'none';
39+
}
40+
41+
if (duplicate) {
42+
return (
43+
<td {...cell.props} style={style}>
44+
{' '}
45+
</td>
46+
);
47+
} else {
48+
return <td {...cell.props} style={style}></td>;
49+
}
50+
};
51+
return (
52+
<div>
53+
<Grid
54+
ref={gridRef}
55+
style={{
56+
height: '500px',
57+
}}
58+
data={gridData}
59+
cellRender={cellRender}
60+
>
61+
<Column field="ProductID" title="ID" width="60px" />
62+
<Column field="ProductName" title="Name" width="250px" />
63+
<Column field="CategoryName" title="CategoryName" />
64+
<Column field="UnitPrice" title="Price" width="80px" />
65+
<Column field="Discontinued" width="120px" />
66+
<Column field="Discontinued2" width="120px" />
67+
</Grid>
68+
</div>
69+
);
70+
};
71+
ReactDOM.render(<App />, document.querySelector('my-app'));
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
[
2+
{
3+
"ProductID": 1,
4+
"ProductName": "Chai",
5+
"SupplierID": 1,
6+
"CategoryID": 1,
7+
"QuantityPerUnit": "10 boxes x 20 bags",
8+
"UnitPrice": 18.0,
9+
"UnitsInStock": 39,
10+
"UnitsOnOrder": 0,
11+
"ReorderLevel": 10,
12+
"Discontinued": false,
13+
"Discontinued2": false,
14+
"CategoryName": "Beverages"
15+
},
16+
{
17+
"ProductID": 2,
18+
"ProductName": "Chang",
19+
"SupplierID": 1,
20+
"CategoryID": 1,
21+
"QuantityPerUnit": "24 - 12 oz bottles",
22+
"UnitPrice": 19.0,
23+
"UnitsInStock": 17,
24+
"UnitsOnOrder": 40,
25+
"ReorderLevel": 25,
26+
"Discontinued": false,
27+
"Discontinued2": false,
28+
"CategoryName": "Beverages"
29+
},
30+
{
31+
"ProductID": 3,
32+
"ProductName": "Aniseed Syrup",
33+
"SupplierID": 1,
34+
"CategoryID": 2,
35+
"QuantityPerUnit": "12 - 550 ml bottles",
36+
"UnitPrice": 10.0,
37+
"UnitsInStock": 13,
38+
"UnitsOnOrder": 70,
39+
"ReorderLevel": 25,
40+
"Discontinued": false,
41+
"Discontinued2": true,
42+
"CategoryName": "Condiments"
43+
},
44+
{
45+
"ProductID": 4,
46+
"ProductName": "Chef Anton's Cajun Seasoning",
47+
"SupplierID": 2,
48+
"CategoryID": 2,
49+
"QuantityPerUnit": "48 - 6 oz jars",
50+
"UnitPrice": 22.0,
51+
"UnitsInStock": 53,
52+
"UnitsOnOrder": 0,
53+
"ReorderLevel": 0,
54+
"Discontinued": false,
55+
"Discontinued2": true,
56+
"CategoryName": "Condiments"
57+
},
58+
{
59+
"ProductID": 5,
60+
"ProductName": "Chef Anton's Gumbo Mix",
61+
"SupplierID": 2,
62+
"CategoryID": 2,
63+
"QuantityPerUnit": "36 boxes",
64+
"UnitPrice": 21.35,
65+
"UnitsInStock": 0,
66+
"UnitsOnOrder": 0,
67+
"ReorderLevel": 0,
68+
"Discontinued": true,
69+
"Discontinued2": true,
70+
"CategoryName": "Condiments"
71+
},
72+
{
73+
"ProductID": 6,
74+
"ProductName": "Grandma's Boysenberry Spread",
75+
"SupplierID": 3,
76+
"CategoryID": 2,
77+
"QuantityPerUnit": "12 - 8 oz jars",
78+
"UnitPrice": 25.0,
79+
"UnitsInStock": 120,
80+
"UnitsOnOrder": 0,
81+
"ReorderLevel": 25,
82+
"Discontinued": false,
83+
"Discontinued2": true,
84+
"CategoryName": "Condiments"
85+
},
86+
{
87+
"ProductID": 7,
88+
"ProductName": "Uncle Bob's Organic Dried Pears",
89+
"SupplierID": 3,
90+
"CategoryID": 7,
91+
"QuantityPerUnit": "12 - 1 lb pkgs.",
92+
"UnitPrice": 30.0,
93+
"UnitsInStock": 15,
94+
"UnitsOnOrder": 0,
95+
"ReorderLevel": 10,
96+
"Discontinued": false,
97+
"Discontinued2": false,
98+
"CategoryName": "Produce"
99+
},
100+
{
101+
"ProductID": 8,
102+
"ProductName": "Northwoods Cranberry Sauce",
103+
"SupplierID": 3,
104+
"CategoryID": 2,
105+
"QuantityPerUnit": "12 - 12 oz jars",
106+
"UnitPrice": 40.0,
107+
"UnitsInStock": 6,
108+
"UnitsOnOrder": 0,
109+
"ReorderLevel": 0,
110+
"Discontinued": false,
111+
"Discontinued2": true,
112+
"CategoryName": "Condiments"
113+
},
114+
{
115+
"ProductID": 9,
116+
"ProductName": "Mishi Kobe Niku",
117+
"SupplierID": 4,
118+
"CategoryID": 6,
119+
"QuantityPerUnit": "18 - 500 g pkgs.",
120+
"UnitPrice": 97.0,
121+
"UnitsInStock": 29,
122+
"UnitsOnOrder": 0,
123+
"ReorderLevel": 0,
124+
"Discontinued": true,
125+
"Discontinued2": true,
126+
"CategoryName": "Meat/Poultry"
127+
},
128+
{
129+
"ProductID": 10,
130+
"ProductName": "Ikura",
131+
"SupplierID": 4,
132+
"CategoryID": 8,
133+
"QuantityPerUnit": "12 - 200 ml jars",
134+
"UnitPrice": 31.0,
135+
"UnitsInStock": 31,
136+
"UnitsOnOrder": 0,
137+
"ReorderLevel": 0,
138+
"Discontinued": false,
139+
"Discontinued2": false,
140+
"CategoryName": "Seafood"
141+
}
142+
]
143+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: Merge Rows in the Grid
3+
description: An example on how to merge cells and rows data in the KendoReact Grid.
4+
type: how-to
5+
page_title: Merge Rows and Cells Data in the Grid - KendoReact Grid
6+
slug: merge-row-and-cell-in-the-grid
7+
tags: grid, rows, merge, cells
8+
res_type: kb
9+
category: knowledge-base
10+
---
11+
12+
## Environment
13+
14+
<table>
15+
<tbody>
16+
<tr>
17+
<td>Product Version</td>
18+
<td>7.0.2</td>
19+
</tr>
20+
<tr>
21+
<td>Product</td>
22+
<td>Progress® KendoReact</td>
23+
</tr>
24+
</tbody>
25+
</table>
26+
27+
28+
## Description
29+
30+
How can I merge or group duplicate cells and rows data in the KendoReact Data Grid?
31+
32+
## Solution
33+
34+
For simple scenarios where the data needs to be merged for single column, rowSpan can be set to the TD elements within the cellRender of the Grid. However, due to limitations in how HTML table can rowSpan/colSpan, it is not possible to have different colSpan for rows that already have set rowSpan, so using colSpan and rowSpan for merging duplicate rows and cells data will not be possible and different approach must be used.
35+
36+
For this scenario, use a [`cellRender`]({% slug api_grid_gridprops %}#toc-cellrender) and compare the previous cell and previous row data to remove the content of the cell if it duplicate. You can also add different colors of the cell based on the values (suitable for boolean values for example), so they can be distinguished visually.
37+
38+
{% meta id:index height:760 %}
39+
{% embed_file grid/merge-rows-and-cells/main.jsx preview %}
40+
{% embed_file grid/merge-rows-and-cells/products.json %}
41+
{% endmeta %}
42+

0 commit comments

Comments
 (0)