# Grouping with Aggregation
URL: https://pro.rv-grid.com/guides/data-manage/grouping-aggregation/
Source: src/content/docs/guides/data-manage/grouping-aggregation.mdx
Description: Learn how to implement data grouping with custom aggregation functions in RevoGrid
## Overview

The Grouping with Aggregation feature allows you to organize your data into hierarchical groups and display custom aggregated values for each group. This is particularly useful for displaying summary statistics, totals, averages, or custom calculations for grouped data.

## Key Features

- **Hierarchical Grouping**: Group data by multiple columns in a tree-like structure
- **Custom Aggregations**: Define custom aggregation functions for different data types
- **Visual Indicators**: Expandable/collapsible groups with aggregation values displayed
- **Flexible Templates**: Customize how group headers and aggregations are displayed

## Basic Usage

## Implementation

### 1. Import Required Components

```typescript
import { groupingAggregation } from '@revolist/revogrid-pro';
```

### 2. Define Aggregation Functions

Create custom aggregation functions for different columns. **Important**: Aggregation functions receive an array of complete data objects, not just the column values. You need to extract the specific property you want to aggregate:

```typescript
const aggregations = {
  price: (values: any[]) => {
    const prices = values.map(item => item.price);
    const sum = prices.reduce((acc, val) => acc + val, 0);
    const avg = sum / prices.length;
    return `Avg: $${avg.toFixed(2)}`;
  },
  quantity: (values: any[]) => {
    const quantities = values.map(item => item.quantity);
    const total = quantities.reduce((acc, val) => acc + val, 0);
    return `Total: ${total}`;
  },
  product: (values: any[]) => {
    return `${values.length} products`;
  }
};
```

### 3. Create Group Template

Use the `groupingAggregation` function to create a template that displays aggregations:

```typescript
const groupTemplate = (h: any, props: any) => {
  return groupingAggregation(h, props, aggregations);
};
```

### 4. Configure Columns

Apply the group template to columns that will be used for grouping:

```typescript
const columns = [
  { name: '🆔 ID', prop: 'id', size: 60 },
  { name: '📂 Category', prop: 'category', size: 120, template: groupTemplate },
  { name: '📁 Subcategory', prop: 'subcategory', size: 120, template: groupTemplate },
  { name: '📦 Product', prop: 'product', size: 150 },
  { name: '💰 Price', prop: 'price', size: 100 },
  { name: '📊 Quantity', prop: 'quantity', size: 100 },
  { name: '📅 Order Date', prop: 'orderDate', size: 120 },
  { name: '🚚 Delivery Date', prop: 'deliveryDate', size: 120 },
  { name: '👤 Customer', prop: 'customer', size: 150 },
  { name: '🌍 Region', prop: 'region', size: 100 },
  { name: '📋 Status', prop: 'status', size: 100 },
];
```

### 5. Set Up Grouping Configuration

Define which columns should be used for grouping:

```typescript
const grouping = {
  props: ['orderDate', 'category', 'subcategory']
};
```

### 6. Initialize the Grid

```typescript
const grid = document.createElement('revo-grid');
grid.source = yourData;
grid.columns = columns;
grid.grouping = grouping;
// Grouping is a built-in feature, no plugin needed
```

## Aggregation Function Examples

### Numeric Aggregations

```typescript
// Average
price: (values: any[]) => {
  const prices = values.map(item => item.price);
  const avg = prices.reduce((acc, val) => acc + val, 0) / prices.length;
  return `Avg: $${avg.toFixed(2)}`;
}

// Sum
quantity: (values: any[]) => {
  const quantities = values.map(item => item.quantity);
  const total = quantities.reduce((acc, val) => acc + val, 0);
  return `Total: ${total}`;
}

// Min/Max
price: (values: any[]) => {
  const prices = values.map(item => item.price);
  const min = Math.min(...prices);
  const max = Math.max(...prices);
  return `Range: $${min} - $${max}`;
}
```

### String Aggregations

```typescript
// Count
product: (values: any[]) => {
  return `${values.length} products`;
}

// Concatenation
names: (values: any[]) => {
  const names = values.map(item => item.name);
  return names.join(', ');
}

// Unique count
categories: (values: any[]) => {
  const categories = values.map(item => item.category);
  const unique = new Set(categories);
  return `${unique.size} unique categories`;
}
```

### Date Aggregations

```typescript
// Date range
orderDate: (values: any[]) => {
  const dates = values.map(item => new Date(item.orderDate));
  const sorted = dates.sort((a, b) => a.getTime() - b.getTime());
  const earliest = sorted[0].toLocaleDateString();
  const latest = sorted[sorted.length - 1].toLocaleDateString();
  return `${earliest} - ${latest}`;
}
```

## Advanced Configuration

### Custom Group Header Styling

You can customize the appearance of group headers by modifying the template function:

```typescript
const customGroupTemplate = (h: any, props: any) => {
  const aggregationValue = getAggregationValue(props);

  return h('div', {
    style: {
      display: 'flex',
      alignItems: 'center',
      gap: '8px',
      padding: '4px 8px',
      backgroundColor: '#f0f0f0',
      borderRadius: '4px'
    }
  }, [
    h('span', { style: { fontWeight: 'bold' } }, props.name),
    h('span', { style: { fontSize: '12px', color: '#666' } }, `(${aggregationValue})`)
  ]);
};
```

### Conditional Aggregations

You can apply different aggregation logic based on the column or group:

```typescript
const conditionalAggregations = {
  price: (values: any[]) => {
    const prices = values.map(item => item.price);
    const sum = prices.reduce((a, b) => a + b, 0);
    const avg = sum / prices.length;
    return `Avg: $${avg.toFixed(2)}`;
  }
};
```

## Best Practices

1. **Performance**: Keep aggregation functions lightweight, especially with large datasets
2. **User Experience**: Provide clear, meaningful aggregation labels
3. **Data Types**: Ensure aggregation functions handle the correct data types
4. **Error Handling**: Add validation for edge cases (empty arrays, null values)
5. **Accessibility**: Use descriptive text for screen readers

## Common Use Cases

- **Sales Reports**: Group by region/category with revenue totals
- **Inventory Management**: Group by department with stock quantities
- **Financial Data**: Group by account type with balance summaries
- **Project Management**: Group by team with task counts and completion rates
