diff --git a/latte/cs/cookbook/grouping.texy b/latte/cs/cookbook/grouping.texy
index 32a799a771..2de4f8c46f 100644
--- a/latte/cs/cookbook/grouping.texy
+++ b/latte/cs/cookbook/grouping.texy
@@ -8,10 +8,10 @@ Filtr a funkce `|group` umožňují efektivní seskupení dat podle zadaného kr
Každá z těchto značek nabízí specifické možnosti pro práci s daty, čímž se stávají nepostradatelnými nástroji pro dynamické a strukturované zobrazení informací v Latte šablonách.
-Filtr a funkce `group`
-----------------------
+Filtr a funkce `group` .{data-version:3.0.16}
+=============================================
-Dejme tomu, že máme následující databázovou tabulku, kde jsou položky rozdělené do kategorií:
+Představte si databázovou tabulku `items` s položkami rozdělenou do kategorií:
| id | categoryId | name
|------------------
@@ -22,7 +22,7 @@ Dejme tomu, že máme následující databázovou tabulku, kde jsou položky roz
| 5 | 3 | Red
| 6 | 3 | Blue
-Vykreslit položky ve foreach cyklu jako seznam je samozřejmě snadné:
+Jednoduchý seznam všech položek pomocí Latte šablony by vypadal takto:
```latte
@@ -32,7 +32,7 @@ Vykreslit položky ve foreach cyklu jako seznam je samozřejmě snadné:
```
-Ale co kdybychom chtěli, aby každá kategorie byla v samostatném seznamu? Jinými slovy, řešíme úkol, jak seskupit položky v lineárním seznamu ve foreach cyklu do skupin. Výstup by měl vypadat takto:
+Pokud bychom ale chtěli, aby položky byly uspořádány do skupin podle kategorie, potřebujeme je rozdělit tak, že každá kategorie bude mít svůj vlastní seznam. Výsledek by pak měl vypadat následovně:
```latte
@@ -51,87 +51,90 @@ Ale co kdybychom chtěli, aby každá kategorie byla v samostatném seznamu? Jin
```
-Rovnou si ukážeme, jak snadno a elegantně se dá úkol vyřešit pomocí `|group`:
+Úkol se dá snadno a elegantně vyřešit pomocí `|group`. Jako parametr uvedeme `categoryId`, což znamená, že se položky rozdělí do menších polí podle hodnoty `$item->categoryId` (pokud by `$item` bylo pole, použije se `$item['categoryId']`):
```latte
-{foreach ($items|group: categoryId) as $categoryId => $items}
+{foreach ($items|group: categoryId) as $categoryId => $categoryItems}
- {foreach $items as $item}
+ {foreach $categoryItems as $item}
- {$item->name}
{/foreach}
{/foreach}
```
-Vnější `{foreach}` seskupí položky do pro každou kategorii a pak nad nimi iteruje vnitřní `{foreach}`.
+Filtr lze v Latte použít i jako funkci, což nám dává alternativní syntaxi: `{foreach group($items, categoryId) ...}`.
+Chcete-li seskupovat položky podle složitějších kritérií, můžete v parametru filtru použít funkci. Například, seskupení položek podle délky názvu by vypadalo takto:
```latte
-{foreach $items as $item}
-
- {iterateWhile}
- - {$item->name}
- {/iterateWhile true}
-
+{foreach ($items|group: fn($item) => strlen($item->name)) as $items}
+ ...
{/foreach}
```
-Výsledek bude vypadat takto:
+Je důležité si uvědomit, že `$categoryItems` není běžné pole, ale objekt, který se chová jako iterátor. Pro přístup k první položce skupiny můžete použít funkci [`first()`|latte:functions#first].
-```latte
-
- - Apple
- - Banana
- - PHP
- - Green
- - Red
- - Blue
-
-```
+Tato flexibilita v seskupování dat činí `group` výjimečně užitečným nástrojem pro prezentaci dat v šablonách Latte.
+Vnořené smyčky
+--------------
+
+Představme si, že máme databázovou tabulku s dalším sloupcem `subcategoryId`, který definuje podkategorie jednotlivých položek. Chceme zobrazit každou hlavní kategorii v samostatném seznamu `` a každou podkategorii v samostatném vnořeném seznamu ``:
+
```latte
-{foreach ($items|group: categoryId) as $categoryId => $items}
- {($items|first)->name}
+{foreach ($items|group: categoryId) as $categoryItems}
- {foreach $items as $item}
- - {$item->name}
+ {foreach ($categoryItems|group: subcategoryId) as $subcategoryItems}
+
+ {foreach $subcategoryItems as $item}
+ - {$item->name}
+ {/foreach}
+
{/foreach}
{/foreach}
```
-Vnořené smyčky
---------------
+Spojení s Nette Database
+------------------------
-V rámci jednoho cyklu můžeme vytvářet více vnitřních smyček a dokonce je zanořovat. Takto by se daly seskupovat třeba podkategorie atd.
+Pojďme si ukázat, jak efektivně využít seskupování dat v kombinaci s Nette Database. Předpokládejme, že pracujeme s tabulkou `items` z úvodního příkladu, která je prostřednictvím sloupce `categoryId` spojená s touto tabulkou `categories`:
-Dejme tomu, že v tabulce bude ještě další sloupec `subcategoryId` a kromě toho, že každá kategorie bude v samostatném ``, každá každý podkategorie samostatném ``:
+| categoryId | name |
+|------------|------------|
+| 1 | Fruits |
+| 2 | Languages |
+| 3 | Colors |
+
+Data z tabulky `items` načteme pomocí Nette Database Explorer příkazem `$items = $db->table('items')`. Během iterace nad těmito daty máme možnost přistupovat nejen k atributům jako `$item->name` a `$item->categoryId`, ale díky propojení s tabulkou `categories` také k souvisejícímu řádku v ní přes `$item->category`. Na tomto propojení lze demonstrovat zajímavé využití:
```latte
-{foreach ($items|group: categoryId) as $items1}
+{foreach ($items|group: category) as $category => $categoryItems}
+ {$category->name}
- {foreach ($items1|group: subcategoryId) as $items2}
-
- {foreach $items2 as $item}
- - {$item->name}
- {/foreach}
-
+ {foreach $categoryItems as $item}
+ - {$item->name}
{/foreach}
{/foreach}
```
+V tomto případě používáme filtr `|group` k seskupení podle propojeného řádku `$item->category`, nikoliv jen dle sloupce `categoryId`. Díky tomu v proměnné klíči přímo `ActiveRow` dané kategorie, což nám umožňuje přímo vypisovat její název pomocí `{$category->name}`. Toto je praktický příklad, jak může seskupování zpřehlednit šablony a usnadnit práci s daty.
+
+
+Filtr `|batch`
+==============
-Filtr |batch
-------------
+Filtr umožňuje rozdělit seznam prvků do skupin s předem určeným počtem prvků. Tento filtr je ideální pro situace, kdy chcete data prezentovat ve více menších skupinách, například pro lepší přehlednost nebo vizuální uspořádání na stránce.
-Seskupování lineárních položek obstarává také filtr `batch`, a to do dávek s pevným počtem prvků:
+Představme si, že máme seznam položek a chceme je zobrazit v seznamech, kde každý obsahuje maximálně tři položky. Použití filtru `|batch` je v takovém případě velmi praktické:
```latte
-{foreach ($items|batch:3) as $batch}
+{foreach ($items|batch: 3) as $batch}
{foreach $batch as $item}
- {$item->name}
{/foreach}
@@ -139,23 +142,21 @@ Seskupování lineárních položek obstarává také filtr `batch`, a to do dá
```
-Lze jej nahradit za iterateWhile tímto způsobem:
+V tomto příkladu je seznam `$items` rozdělen do menších skupin, přičemž každá skupina (`$batch`) obsahuje až tři položky. Každá skupina je poté zobrazena v samostatném `` seznamu.
+
+Pokud poslední skupina neobsahuje dostatek prvků k dosažení požadovaného počtu, druhý parametr filtru umožňuje definovat, čím bude tato skupina doplněna. To je ideální pro estetické zarovnání prvků tam, kde by neúplná řada mohla působit neuspořádaně.
```latte
-
-{foreach $items as $item}
- {iterateWhile}
- - {$item->name}
- {/iterateWhile $iterator->counter0 % 3}
-{/foreach}
+{foreach ($items|batch: 3, '—') as $batch}
+ ...
```
Značka `{iterateWhile}`
------------------------
+=======================
-Stejné úkoly, jako jsme řešili s filtrem `|group`, si ukážeme s použitím značky `{iterateWhile}`. Hlavní rozdíl mezi oběma přístupy je v tom, že `group` nejprve zpracuje a seskupí všechny vstupní data, zatímco `{iterateWhile}` řídí průběhu cyklů s podmínkami, takže iterace probíhá postupně.
+Stejné úkoly, jako jsme řešili s filtrem `|group`, si ukážeme s použitím značky `{iterateWhile}`. Hlavní rozdíl mezi oběma přístupy je v tom, že `group` nejprve zpracuje a seskupí všechna vstupní data, zatímco `{iterateWhile}` řídí průběhu cyklů s podmínkami, takže iterace probíhá postupně.
Nejprve vykreslíme tabulku s kategoriemi pomocí iterateWhile:
@@ -197,7 +198,7 @@ Výsledek bude vypadat takto:
```
-K čemu je takové použití iterateWhile dobré? Jak se liší od řešení, které jsme si ukázali úplně na začátku tohoto návodu? Rozdíl je v tom, že když bude tabulka prázdná a nebude obsahovat žádné prvky, nevypíše se prázdné ``.
+K čemu je takové použití iterateWhile dobré? Když bude tabulka prázdná a nebude obsahovat žádné prvky, nevypíše se prázdné ``.
Pokud uvedeme podmínku v otevírací značce `{iterateWhile}`, tak se chování změní: podmínka (a přechod na další prvek) se vykoná už na začátku vnitřního cyklu, nikoliv na konci.
Tedy zatímco do `{iterateWhile}` bez podmínky se vstoupí vždy, do `{iterateWhile $cond}` jen při splnění podmínky `$cond`. A zároveň se s tím do `$item` zapíše následující prvek.