Id Status Emojis (template) Birthday Age
One 👍 23. 2. 1982 42
Two 🤦‍♀️ 2. 1. 1997 27
Trhee 👍 21. 5. 1955 69
4 👍 23. 5. 1964 60
5 🤦‍♀️ 23. 8. 1939 85
6 🤪 25. 9. 1985 39
7 🤪 11. 3. 1974 50
8 🤪 23. 5. 1946 78
9 🤪 20. 4. 1944 80
10 👍 10. 4. 1981 43
11 👍 19. 9. 1994 30
12 🤪 19. 1. 1936 88
13 🤪 27. 9. 1978 46
14 🤪 15. 12. 1977 46
15 👍 3. 3. 1987 37
16 🤦‍♀️ 11. 2. 1945 79
17 🤪 8. 3. 1983 41
18 🤦‍♀️ 28. 4. 1931 93
19 🤦‍♀️ 27. 10. 1949 75
20 🤪 14. 8. 1941 83
Ids sum: 210 Avg Age: 60
( Items: 1 - 20 from 1020 )
  See the code below 👇 or see GitHub
public function createComponentGrid(): DataGrid
{
	$grid = new DataGrid();

	$grid->setDefaultSort(['id' => 'ASC']);

	$grid->setDataSource($this->dibiConnection->select('*')->from('users'));

	$grid->setItemsPerPageList([20, 50, 100], true);

	$grid->addColumnText('id', 'Id')
		->setReplacement([
			1 => 'One',
			2 => 'Two',
			3 => 'Trhee',
		])
		->setSortable();

	$grid->addColumnLink('email', 'E-mail', 'this')
		->setSortable();

	$columnStatus = $grid->addColumnStatus('status', 'Status');

	$columnStatus
		->addOption('active', 'Active')
		->endOption()
		->addOption('inactive', 'Inactive')
		->setClass('btn-warning')
		->endOption()
		->addOption('deleted', 'Deleted')
		->setClass('btn-danger')
		->endOption()
		->setSortable();
	$columnStatus->onChange[] = [$this, 'changeStatus'];

	$grid->addColumnText('emojis', 'Emojis (template)')
		->setTemplate(__DIR__ . '/Templates/grid/columnsEmojis.latte');

	$grid->addColumnDateTime('birth_date', 'Birthday')
		->setFormat('j. n. Y')
		->setSortable();

	$grid->addColumnNumber('age', 'Age')
		->setRenderer(fn (Row $row): ?int => DateTime::fromSafe($row->asDateTime('birth_date'))?->diff(new DateTime())->y);

	$grid->setColumnsHideable();

	/*$grid->setColumnsSummary(['id'])
		->setRenderer(function(int $summary, string $column): string {
			return 'Summary renderer: ' . $summary . ' $';
		});*/

	$grid->addColumnCallback('status', function (ColumnStatus $column, Row $row): void {
		if ($row['id'] === 3) {
			$column->removeOption('active');
		}
	});

	$grid->addColumnCallback('email', function (ColumnLink $column, Row $row): void {
		if ($row['id'] === 3) {
			$column->setRenderer(fn (): string => '');
		}
	});

	// $grid->addAggregationFunction('status', new FunctionSum('id'));

	$grid->setMultipleAggregationFunction(
		new class implements IMultipleAggregationFunction
		{

			private int $idsSum = 0;

			private float $avgAge = 0.0;

			public function getFilterDataType(): string
			{
				return IAggregationFunction::DATA_TYPE_PAGINATED;
			}

			public function processDataSource(mixed $dataSource): void
			{
				if (!$dataSource instanceof Fluent) {
					throw new UnexpectedValueException();
				}

				$this->idsSum = Types::forceInt($dataSource->getConnection()
					->select('SUM([id])')
					->from($dataSource, '_')
					->fetchSingle());

				$this->avgAge = round(Types::forceNumber($dataSource->getConnection()
					->select('AVG(YEAR([birth_date]))')
					->from($dataSource, '_')
					->fetchSingle()));
			}

			public function renderResult(string $key): string
			{
				if ($key === 'id') {
					return 'Ids sum: ' . $this->idsSum;
				}

				if ($key === 'age') {
					return 'Avg Age: ' . ((int) date('Y') - $this->avgAge);
				}

				return '';
			}

		}
	);

	return $grid;
}