Produkty Objednávky Zákazníci Dokumentace
Nepřihlášen Uživatel 1 Uživatel 2 Uživatel 3
Část III · Sloupce

6. Sloupce a presety

add() vypíše hodnotu tak, jak přišla z datového zdroje. Všechny ostatní add*() metody jsou jen add() s předvyplněným formátováním, filtrem a typem pro export – nic víc v nich není.

Ukázka

Od každého presetu jeden sloupec. Dvojice Utraceno a Aktivní jsou pokaždé tatáž hodnota dvakrát – jednou s presetem, jednou bez něj.

Zdrojový kód

php app/Modules/AdminModule/Components/Docs/Columns/ColumnTypesGridControl/ColumnTypesGridControl.php
<?php

declare(strict_types=1);

namespace App\Components\Docs\Columns\ColumnTypesGridControl;

use Xart\Grid\Button\ButtonManager;
use Xart\Grid\Column\ColumnManager;
use Xart\Grid\Control\GridControl;
use Xart\Grid\DataOutput\Row;
use Xart\Grid\DataSource\DataSource;
use Xart\Grid\DataSource\SQL\SQLDataSource;

/**
 * Dokumentace, kapitola 6 – Sloupce a presety.
 *
 * Seznam zákazníků, ve kterém je od každého presetu jeden sloupec. Dvojice sloupců nad touž
 * hodnotou (spent/spent_raw a is_active/is_active_text) ukazují, co preset dělá navíc proti add().
 */
class ColumnTypesGridControl extends GridControl
{
    public function createDataSource(): DataSource
    {
        return new SQLDataSource(__DIR__ . '/ColumnTypesGridControl.sql');
    }


    public function columns(ColumnManager $cm): void
    {
        // Bez presetu: hodnota jde do buňky tak, jak přišla z databáze, filtr je textový.
        $cm->add('name', 'Zákazník');

        $cm->addEmail('email', 'E-mail');
        $cm->addPhone('phone', 'Telefon');

        // Číslo bez desetinných míst a bez jednotky.
        $cm->addNumber('orders_count', 'Objednávek', 0);

        // Dvě desetinná místa a jednotka za číslem.
        $cm->addNumber('spent', 'Utraceno', 2, 'Kč');

        // Tatáž hodnota obyčejným add() – pro srovnání, co všechno preset udělá navíc.
        $cm->add('spent_raw', 'Utraceno přes add()');

        // Ano/ne jako ikona, a hned vedle totéž jako text.
        $cm->addCheck('is_active', 'Aktivní');
        $cm->addBoolean('is_active_text', 'Aktivní textem');

        $cm->addDate('registered_on', 'Registrace');
        // Sloupec typu TIME přijde z databáze jako DateInterval a preset pro něj formatter nemá –
        // proto je čas složený už v dotazu (DATE_FORMAT), tedy jako řetězec „HH:MM“.
        $cm->addTime('registered_at', 'Čas registrace');

        // Odstup od teď („před 3 dny“); přesný okamžik je v titulku buňky.
        $cm->addDatetime('last_order_at', 'Poslední objednávka', true);
    }


    public function buttons(ButtonManager $bm): void
    {
    }


    public function rows(Row $row): void
    {
    }


    public function render(): void
    {
        $this->template->render(__DIR__ . '/ColumnTypesGridControl.latte');
    }
}
sql app/Modules/AdminModule/Components/Docs/Columns/ColumnTypesGridControl/ColumnTypesGridControl.sql
SELECT
    c.id,
    CONCAT(c.first_name, ' ', c.last_name) AS name,
    c.email,
    c.phone,
    (SELECT COUNT(*) FROM `order` o WHERE o.id_customer = c.id) AS orders_count,
    (SELECT COALESCE(SUM(o.total_price), 0) FROM `order` o WHERE o.id_customer = c.id) / 100 AS spent,
    (SELECT COALESCE(SUM(o.total_price), 0) FROM `order` o WHERE o.id_customer = c.id) / 100 AS spent_raw,
    c.is_active,
    c.is_active AS is_active_text,
    DATE(c.created_at) AS registered_on,
    DATE_FORMAT(c.created_at, '%H:%i') AS registered_at,
    (SELECT MAX(o.created_at) FROM `order` o WHERE o.id_customer = c.id) AS last_order_at
FROM `customer` c

Alias a titulek

První parametr je alias – musí odpovídat aliasu ve výsledku dotazu, jinak grid skončí chybou (stejně jako dvakrát přidaný tentýž alias). Druhý je nepovinný titulek; bez něj se v hlavičce vypíše alias. Nastavit ho jde i dodatečně přes setTitle(), každá add*() metoda vrací vytvořený sloupec.

Dotaz musí vracet id, i když z něj sloupec neděláte – v ukázce v columns() není.

Co sloupec umí hned

  • filtr – u add() textový (LIKE), u presetů ten, který se k typu hodí; operátor si uživatel u sloupcového filtru nevybírá,
  • řazení klikem na hlavičku (se Shiftem na víc úrovní) – řadí databáze podle původní hodnoty, ne podle toho, co preset vykreslil,
  • místo v dialogu Zobrazení → Sloupce: skrytí, přesun, změna šířky,
  • účast v globálním hledání a v exportu.

Presety

MetodaV buňceFiltrExport
add() hodnota z databáze beze změny texttext
addNumber($a, $t, $decimals = 2, $unit = null) 1 234,50 Kč – oddělené tisíce, pevný počet desetinných míst, jednotka, zarovnání doprava rozsah od–dočíslo
addDate($a, $t, $relative = false) 24.08.2026 rozsah datdatum
addDatetime($a, $t, $relative = false) datum a pod ním čas rozsah s časemdatum a čas
addTime() hodnota beze změny rozsah časůčas
addBoolean($a, $t, $yesLabel, $noLabel, $yesValue, $noValue) Ano / Ne textem nabídkatext
addCheck(…) zelená fajfka / červený křížek nabídkaAno / Ne
addEmail() odkaz mailto: texttext
addPhone($a, $t, $link = true) +420 777 123 456 – přeskládané do trojic, odkaz tel: texttext

Sloupce pro nabídku hodnot (addSelect(), addEnum()), barvu, avatar a systémový sloupec mají vlastní kapitoly.

Relativní datum

addDate() i addDatetime() berou třetí parametr $relative: v buňce pak stojí „před 3 dny“ a přesný údaj se schová do jejího titulku (najeďte myší na Poslední objednávku). Do exportu jde vždy přesné datum – „před 3 dny“ by v sešitu za týden lhalo. Sloupec bez času počítá jen celé dny, protože datum z databáze je půlnoc.

Na co si dát pozor

  • Jednotka jde jen do buňky, ne do exportu – v sešitu má zůstat holé číslo, se kterým jde počítat (kapitola 40).
  • Nečíselná hodnota (prázdno, NULL, text) nechá buňku addNumber() prázdnou.
  • Zarovnání dělá třída text-end; přebít ho jde v rows() přes removeClass() (kapitola 15).
  • Co telefon nepřipomíná („777 123 456 kl. 22“, poznámka místo čísla), se vypíše tak, jak přišlo, a odkaz nedostane. Totéž platí pro addEmail(): mailto: na nesmysl je horší než nic.
  • addTime() zatím žádný formatter nemá. Sloupec typu TIME vrací Nette Database jako DateInterval, který se do buňky nemá jak vypsat – v ukázce proto čas skládá už dotaz (DATE_FORMAT(created_at, '%H:%i')).
  • Peníze dělí SQL (total_price / 100); filtr se poskládá nad výrazem, řadí se podle aliasu – obojí databáze unese.