ublaboo/datagrid: mocný, rychlý, rozšiřitelný, hezký, anglicky dokumentovaný datagrid

Pavel Janda
Člen | 977
+
0
-

@Mart78 Máš práva ke čtení/zápisu souboru databáze?

Mart78
Člen | 31
+
0
-

@PavelJanda jop, je to na localhostu, v CD-collection to jde, v mém projektu ne, a config, model i databázi mám z cd-collection

Pavel Janda
Člen | 977
+
0
-

@Mart78 Zkus někam picnout zip toho projektu. Nebo na github třeba, pak to smažeš.

Mart78
Člen | 31
+
0
-

@PavelJanda link .. můžeš zkusit, já už to vidím snad na nějakej bug

Editoval Mart78 (1. 6. 2016 20:08)

Pavel Janda
Člen | 977
+
+1
-

@Mart78 Zkus mrknout do config.local.neon, jestli si tam náhodou nepřepisuješ databázi.

Mart78
Člen | 31
+
0
-

@PavelJanda jeej, tak to jsem přehlídl, díky moc :) jdu si užívat krás datagridu

kralik
Člen | 230
+
0
-

Ahoj,
právě testuji tento datagrid a zatím super.

Mám prosbičku. Mohu nějak $grid->addColumnStatus(…) předat hodnoty v poli.
Resp. Pro ->addOption(…) předat pole?

Moc díky

Pavel Janda
Člen | 977
+
0
-

@kralik Přidal jsem do tagu 4.2.3. Ukázka:

$grid->addColumnStatus('status', 'Status')
	->setOptions([1 => 'Online', 2 => 'Standby'])
	->onChange[] = [$this, 'changeStatus'];

Pokud chceš potom přistoupit k jednotlivým Options, potom takto:

$grid->getColumn('status')->getOption(2)->setClass('btn-primary');
kralik
Člen | 230
+
+1
-

Chápu-li to správně tak to budu moci takto použít, že ano?
$options = array(1 ⇒ ‚OK‘, 2 ⇒ ‚ERR‘);

$options bude načteno z databáze.

<?php
$grid->addColumnStatus('status', 'Status')
    ->setOptions($options)
?>

Mooc díky

Pavel Janda
Člen | 977
+
0
-

@kralik Ano, takhle je to cajk.

FJP
Člen | 124
+
+1
-

Pavel Janda napsal(a):

@FJP Můžeš k tomu server erroru poslat nějakou hlášku?

Pardon, měl jsem na ostrém, špatnou verzi.

David Kregl
Člen | 52
+
0
-

Ahoj @PavelJanda
Nejprve bych Ti chtěl poděkovat za datagrid, který je konečně awesome! Mám dvě otázky:

  1. Je možné přidávat tlačítka do pravého horního rohu gridu? (tam, kde se zobrazuje tlačítko na přidání řádku a skrývání sloupců)
  2. Jak mohu při vypisování sloupcí za použití Database/Context sáhnout do jiné tabulky? Mám strukturu 1:m a v tabulce users ukládám id kategorie a z tabulky categories následně chci vytáhnout title kategorie.

Díky!

Pavel Janda
Člen | 977
+
0
-

@DavidKregl Jaká tlačítka by jsi tam chtěl přidávat? Není problém něco takového dopsat.

Jak chceš vypisovat ty názvy kategorií? Oddělené nějakým delimiterem (GROUP_CONCAT()), nebo s nimi chceš dělat složitější věci?

Jako nejjednodušší implementace výpisu všech kategorií u uživatele se mi jeví: udělat si renderer, který dostane IRow a tím pádem můžeš iterovat nad souvisejícími záznamy z tabulky category. Nastíním v příkladu (Ale všechno tipuji, nepracuji s NDBT):

$grid->addColumnText('categories', 'Kategorie')
	->setRenderer(function($row) {
		return implode(', ', $row->retated('category')->fetchPairs('id', 'title'));
	});

A nebo uděláš totéž v šabloně (/ bloku šablony):

{foreach $item->related('category') as $category}
	{$category->title}
	{sep}, {/sep}
{/foreach}
David Kregl
Člen | 52
+
+1
-

Díky za rychlou odpověd.

Představuji si to jako klasické přidávání akcí, takže něco jako:

$grid->addToolbarAction('do something', 'something', 'doSomething!');

Momentálně bych si tam chtěl přidat tlačítko na schovávání filtrů (BS Collapse).

Editoval David Kregl (31. 5. 2016 19:34)

Pavel Janda
Člen | 977
+
0
-

@DavidKregl No proč neřekneš rovnou, ať přidám takovouhle pěknou věc? :) Oboje je dobrý nápad.

Zatím přidám ty tlačítka nahoře a uvidíme, jak mi projde hlavou ten collapse. Jak to děláš ty? Mohl bys ukázat nějaký screenshot tvého gridu? Používáš vnější renderování filtrů? Máš hodně custom template/css? Nebo standard?

Editoval Pavel Janda (31. 5. 2016 19:41)

David Kregl
Člen | 52
+
0
-

@PavelJanda Jsem rád, že se Ti můj nápad líbí, ještě dnes Ti pošlu symbolický donate.
Můj grid zatím vypadá takhle: http://jpeg.cz/…/31/TJ4d.png

Používám vnější renderování filtrů, a tak si to představují nějak takhle:

$grid->setFiltersHideable();

A očekával bych, že se celý <div class=„row row-filters“></div> obalí patřičným elementem, aby si BS sám inicializoval ten collapse (viz http://getbootstrap.com/javascript/#…).

Editoval David Kregl (31. 5. 2016 20:23)

FJP
Člen | 124
+
0
-

Ahoj,
opět se ozívám s group action.

Když je pod sebou více gridů, tak tomu druhému nefungují skupinové akce. Domnívám se, že se tam ještě tlučou názvy (např: group_action_item1 atd.) …

FJP

FJP
Člen | 124
+
0
-

Mohl by jste někdo dát příklad funkce handleSort? Mám s tím problém.

    public function handleSort(array $ids, $item_id = null, $prev_id = null, $next_id = null) {
        $httpRequest = $this->context->getByType('Nette\Http\Request');
        dump($httpRequest);
        dump($next_id);
        dump($item_id);
        die;
        $category = $httpRequest->getQuery('category');
...
}

Navíc to nic nevydumpuje. Můžu nějak získat pole všech id? … chtěl bych použít tuto funkci:

function updateOrder($id_array, $category_id){
    $count = 1;
    foreach ($id_array as $id) {
        $update = $this->getService('categoryProduct')->findBy(array(
            'product_id' => $id,
            'category_id' => $category_id
            ))
            ->update(array(
            'ordering' => $count
        ));
        $count ++;
    }
    return true;
}
Pavel Janda
Člen | 977
+
0
-

@FJP O víkendu se nato podívám, díky za report.

fizzy
Backer | 49
+
0
-

@FJP uz som to tu raz daval:

public function handleSort($item_id, $prev_id, $next_id){
        $prevRow = $this->database->table("tabulka")->where("id", $prev_id)->fetch();
        $newOrderId = $prevRow ? $prevRow->position + 1 : 1;
        $this->database->query("UPDATE tabulka SET position = position + 1 WHERE position >= ?", $newOrderId);
        $this->database->query("UPDATE tabulka SET position = ? WHERE id = ?", $newOrderId, $item_id);
    }
sibka
Člen | 24
+
0
-

@PavelJanda Ahoj, narazila jsem na jednu chybku v NetteDatabaseTableMssqlDataSource.php. Při použití filtru typu DateRange se mi to nefitrovalo včetně zadaného data.

Všimla jsem si nesouladu formátu data ve funkci applyFilterDateRange (řádek 40)

Parametr 112 formátuje na yyyymmdd, ale datum z filtru je ve formátu Y-m-d (správně by mělo být Ymd).

Editoval sibka (3. 6. 2016 10:03)

pitr82
Člen | 121
+
0
-

Sortování:
mám sortování podle cizího klíče.

V sloupci se může vyskytovat null hodnota.
když třídím ručně, tak to sortuje i null hodnoty.

EDIT: i když jsem nahradil null hodnoty za cizí klíče, tak problém přetrvává

http://localhost/testGrid/?myGrid-sort[u.name]=ASC
  • tohle funguje

když odejdu na jinou stránku a vrátím se zpět na grid, vyhodí chybu :

Ublaboo\DataGrid\Exception\DataGridException
There is no column at key [u.name] defined

Pamatuje si, že chce sortit podle cizího sloupce a s null hodnotou si zřejmě neporadí.
Jde zakázat aby si pamatoval nastavení gridu v session ?

Dotaz pro grid

return $this->em->getRepository(Test::class)->createQueryBuilder('t')
		->leftJoin("t.user","u");

Editoval pitr82 (8. 6. 2016 6:15)

David Kregl
Člen | 52
+
0
-

@pitr82 Možná hledáš tohle:

$grid->setRememberState(FALSE);
Pavel Janda
Člen | 977
+
0
-

@pitr82 Jakou používáš verzi? Sortící klíč přenášený v URL už by se neměl dlouho přenášet podle jména sloupce, ale podle klíče sloupce.

pitr82
Člen | 121
+
0
-

@DavidKregl dík, tohle zabralo.

@PavelJanda jedu na masteru. Kdyz nastavím třídění podle tohoto sloupce, tak při zapamatování třídění a obnovení stránky mi to napíše tuto chybu. musím pak ručně zadat: „http://localhost/testGrid/?myGrid-sort[u.name]=ASC“ a třídění zrušit… Nechápu, proč to normáoně třídí a při opětovném načtení stránky to vypíše chybu.
V laděnce je :

Ublaboo\DataGrid\DataGrid->getColumn  že přijíma $key="u.name"

A gridu je Column takto (user != u.name):

$grid->addColumnText('user', 'Uživatel', 'user.name')
		->setSortable('u.name')
		->setAlign('left')
		->setFilterText('u.name');

při volání adtagridu je třídění nastaveno správně

sort => array (1)
"u.name" => "ASC"
Pavel Janda
Člen | 977
+
0
-

@pitr82 Díky za report. Zatím je to fixnuté v masteru. Otagované to bude v příští verzi.

Můžeš si zase zapnout session.

Editoval Pavel Janda (10. 6. 2016 8:20)

pitr82
Člen | 121
+
0
-

@PavelJanda Super díky

Jen mám ještě dotaz. pokud chci defaultně sortit podle více sloupců

$grid->setDefaultSort(['access' => 'ASC', 'priority' => 'ASC']);

Tak se sortí jen podle posledního >> priority, lze to nějak kromě použití přímo v dotazu ?

$grid->addColumnText('name', 'Name')
	->setSortable()
	->setSortableCallback(function($datasource, $sort) {

jazk zde zjistim, zda bylo kliknuto na ASC nebo DESC ze kterého parametru to vytáhnu ?

	});
Pavel Janda
Člen | 977
+
0
-

@pitr82 Sortění je momentálně implementované pouze opdlejednoho sloupce. Nějak jsem zatím nepřišel na UX návrh vícero sortítek, který by se mi líbil.

V tom sort bys měl mít něco jako [‚name‘ ⇒ ‚ASC‘]

Pavel Janda
Člen | 977
+
+1
-

Nová verze – v4.3.0

  • DataGrid je možné používat bez auto-submitu. Objeví se tlačítko (přizpůsobitelné, stejně jako action a pod – icon, class, …) – http://ublaboo.org/datagrid/filter#…
  • Možnost určit defaultní počet položek na stránce – http://ublaboo.org/datagrid/column#…
  • Metoda html formuláře filtrů datagridu byla dříve GET, nyní je POST. V podstatě by se to nemělo nijak projevit – URL se refreshuje pomocí history api stejně a jinde ta funkčnost též zůstává stejná. Je to možné změnit zpět, jedná se o statickou proměnnou: DataGrid::$form_method.
  • Přibyla možnost přidání BOM do csv exportů
  • Přibyly tlačítka v záhlaví tabulky – ToolbarButton(s) – http://ublaboo.org/datagrid/action#…
  • Pár dalších drobností a pár fixů

Editoval Pavel Janda (12. 6. 2016 19:07)

sibka
Člen | 24
+
0
-

@PavelJanda Dovoluji si se připomenout :-)

sibka napsal(a):

@PavelJanda Ahoj, narazila jsem na jednu chybku v NetteDatabaseTableMssqlDataSource.php. Při použití filtru typu DateRange se mi to nefitrovalo včetně zadaného data.

Všimla jsem si nesouladu formátu data ve funkci applyFilterDateRange (řádek 40)

Parametr 112 formátuje na yyyymmdd, ale datum z filtru je ve formátu Y-m-d (správně by mělo být Ymd).

Pavel Janda
Člen | 977
+
0
-

@sibka Promiň, nějak mi tvů příspěvek zapadnul. Ano, máš pravdu, ISO (112) je yyyymmdd. https://msdn.microsoft.com/…s187928.aspx

Můžeš zkusit master?

Editoval Pavel Janda (15. 6. 2016 9:31)

FJP
Člen | 124
+
0
-

Ahoj, sdílím řazení řádků pomocí tohodle super gridu ;)… já se s tím docela natrápil, možná by to šlo i jednodušeji, dělal jsem to poprvé. Ale říkal jsem si, že to sem dám, kdyby to někomu pomohlo.

public function handleSort($ids, $item_id, $prev_id, $next_id) {
    $prev = $this->context->getService('categoryProduct')
            ->findOneBy(array(
                'product_id' => $prev_id,
                'category_id' => $this->categoryId
            ));
    $item = $this->context->getService('categoryProduct')
            ->findOneBy(array(
                'product_id' => $item_id,
                'category_id' => $this->categoryId
            ));
    $next = $this->context->getService('categoryProduct')
            ->findOneBy(array(
                'product_id' => $next_id,
                'category_id' => $this->categoryId
            ));

    $category = $this->context->getService('categoryProduct')
        ->findBy(array(
                'category_id' => $this->categoryId
            ))
        ->where('product_id <> ?', $item->product_id);

    if ($prev && $next) {
        if ($item->order < $next->order && $item->order < $prev->order) {
            $item->update(array('order' => $prev->order));
            $counter = $prev->order;
            foreach ($category
                ->where('order <= ?', $counter)
                ->order('order DESC') as $item) {
                $counter--;
                $this->context->getService('categoryProduct')
                    ->findOneBy(array(
                        'product_id' => $item['product_id'],
                        'category_id' => $this->categoryId
                    ))->update(array('order' => $counter));
            }
        } elseif ($item->order > $next->order && $item->order > $prev->order) {
            $counter = $next->order;
            $item->update(array('order' => $counter));
            foreach ($category
                ->where('order >= ?', $counter)
                ->order('order ASC') as $item) {
                $counter++;
                $this->context->getService('categoryProduct')
                    ->findOneBy(array(
                        'product_id' => $item['product_id'],
                        'category_id' => $this->categoryId
                    ))->update(array('order' => $counter));
            }
        }
    } elseif ($prev && !$next) {
        $item->update(array('order' => $prev->order + 1));
    } elseif ($next && !$prev) {
        $item->update(array('order' => $next->order - 1));
    }

    if ($this->isAjax()) {
        $this['productsGrid']->reload();
        $this->redrawControl('alerts');
    } else {
        $this->redirect('this');
    }
}

Jeden produkt může být ve více kategoriích, proto je tabulka categoryProduct

sibka
Člen | 24
+
0
-

@PavelJanda V master je to ok. Díky.

Pavel Janda napsal(a):

@sibka Promiň, nějak mi tvů příspěvek zapadnul. Ano, máš pravdu, ISO (112) je yyyymmdd. https://msdn.microsoft.com/…s187928.aspx

Můžeš zkusit master?

pitr82
Člen | 121
+
0
-

@pavelJanda Ahoj, zase jsem se trochu zasekl.
Potřebuji vynásobit výsledek a pro tento výsledek udělat SUM.

Zkoušel jsem to pomocí DB, ale s tím si grid neporadí, protože AddSelect rozšíří pole $item[0,cena]

$this->em->getRepository(Sms::class)->createQueryBuilder('s')
		->addSelect("s.size*u.price AS cena")
		->leftJoin("s.user","u");

Pak jsem zkoušel vlastní renderer

$grid->addColumnNumber('cena', 'Kč')
		 ->setRenderer(function($item) {
		     return $item->user->price * $item->size;
		 });

	   $grid->setColumnsSummary(['size','cena']);

Tohle zase sumne původní sloupec cena, nepoužije výstup z rendereru.

nějký nápad jak na tu SUMU ?

keeper7
Člen | 8
+
0
-

Ahoj libi se me tento grid ale zasekl jsem se na par vecech.

  1. Jak lze pridat attribut na action button aby se otevrela akce v novem okne?
  2. Jak nastavit aby action button predaval jeden nebo vicero parameteru z aktualniho radku napriklad
<?php
// tohleto nefunguje
$grid->addAction('disable', '', 'disable!', ['hash' => $item->hash, 'name'=> $item->name]);
?>

3. Zkousel jsem csv export a u view mam ~200 000 zaznamu a padne na
Allowed memory size of 134217728 bytes exhausted
Pouzivam nettedb. To by asi chtelo poresit nejak jinak.

David Kregl
Člen | 52
+
0
-

@keeper7

1. Co takhle tohle?

->addAttributes(['target' => '_blank'])

2. Defaultně se jako parametr předává id, nemůžeš si ty data vytáhnout v cílové destinaci?

keeper7
Člen | 8
+
0
-

@David Kregl

1.

->addAttributes(['target' => '_blank'])

Bohuzel nefunguje. Podle dokumentace nastavuje atribut pro tr a th. Zajimave je ze jsem je nikde nenasel.

2. Parametry jsem uz poresil

$grid->addAction('disable', '', 'disable!', ['hash' => 'hash', 'name'=> 'nazev_sloupce']);
Pavel Janda
Člen | 977
+
0
-

@keeper7 1, Hmmm, Action dědí od Column a ten Column pomocí ::addAtributes nastavuje atributy právě elementům tr a th. Upravím to. Metoda bude mít jiné chování u Action a bude nastavovat atributy ne sloupci akce, ale odkazu (<a>) akce.

3, No Export by default vyprdne všechny záznamy a jelikož iteruje nad nějakou kolekcí v Nette\Database (asi Nette\Database\Table), fetchne všechny záznamy do pole a ty vypíše do CSV. Nějaký nápad, jak to řešit jinak? Můžeš si udělat vlastní export, který bude dědit nativní CSV export, ale bude brát v potaz nějaký persistentní parametr presenteru (měnitelný), něco jako max csv size.

A nebo použít filtered csv export..

Hlava
Člen | 19
+
0
-

Máš představu, kdy bude kompatibilní s 2.4?

Pavel Janda
Člen | 977
+
0
-

@Hlava Predstavy by byly, ale nechci slibovat, ze to bude hned druhy den. Dnes vecer vyjde takova fajn mala verze a potom je v planu kompatibilita s nette 2.4. Rozhodne je to priorita. O vikendu se na to urcite frknu a ufidime, jak to fujde.

Hlava
Člen | 19
+
+1
-

@PavelJanda Tak věz, že na Tebe budu myslet celý víkend :) A věřím, že nebudu sám ;)

igor.pocta
Člen | 100
+
0
-

@PavelJanda Ahoj, bude podpora i pro Nextras\Orm? :)

Pavel Janda
Člen | 977
+
+4
-

Nová verze – v4.4.0

  • Přidán NextrasDataSource (docu), @igor.pocta , @DavidKregl :)
Pavel Janda
Člen | 977
+
+3
-

Datagrid již funguje na Nette 2.4 (Stejně jako všechny ostatní ublaboo knihovny). Ublaboo.org na nové verzi Nette jede též.

exquis
Člen | 83
+
0
-

Nevím jestli jsem sám, kdo to řeší, ale občas mi blbne setDefaultSort();

Vypozoroval jsem 2 stavy:

  1. občas se stane, že když dám jako default sort [„id“=>„DESC“], tak mi tvrdí, že index neexistuje, což je nesmysl, když jej zohledňuje při generování akcí
  2. není ani tak chyba, ale když se třeba upíši při programování a napíšu IC namísto ID, tak si tuto chybnou volbu uloží do session a neustále tedy hází chybu, že index neexistuje (tentokrát doopravdy neexistuje), takže jediná možnost jak se toho zbavit je zahodit session, což mě i odhlásí, takže je nutné se přihlásit, přejít na stránku, kde jsem skončil atd…jen popravdě netuším, jestli by to šlo nějak rozumně opravit.

Víc mě popravdě štve ta první věc, absolutně nechápu proč to dělá, většiou pomůže, když změním defaultSort na jiný sloupec (např. DATE) a pak to běhá.

Naposledy teď:

function createComponentNavstevnici()
  {
      $Grid = new DataGrid();

      $Grid->setDataSource($this->Visitor->getTblVisitor()->getAll()->select("visitor.*));
      $Grid->setItemsPerPageList($this->itemsPerPage);
      //$Grid->setDefaultSort(["last_change" => "DESC"]);

      $Grid->addColumnText("visible", "Aktivní");
      $Grid->addColumnLink("name", "Název", "detailNavstevnika");
      $Grid->addColumnText("created", "Vytvořeno");
      $Grid->addColumnText("last_change", "Posl. změna");
      $Grid->addColumnText("agent", "Prohlížeč");

      return $Grid;
  }

Editoval exquis (4. 7. 2016 16:21)

Hlava
Člen | 19
+
0
-

@exquis Problém se session mně osobně vadí hodně a budu rád za odstranění :) Ale u toho ID – jestli to dobře chápu, tak aby si mohl řadit podle sloupce ID, tak jej musíš mít zobrazený. Pokud podle něj chceš řadit, pak by asi i zobrazený být měl.

@PavelJanda Nejdříve díky za superrychlé nasazení na 2.4.

Pak ale mám jeden problém s Datagrid – Pokud používám addInlineAdd, viz:

$grid->addInlineAdd()->onControlAdd[] = function($container) {
    /** @var $container Form */
    $container->addText('id')->setAttribute('readonly');
    $container->addText('username','username')->setRequired()->setAttribute('placeholder','username');
    $container->addSelect('language', '', array('cs', 'en', 'sk'));
    $container->addPassword('password')->setRequired()->setAttribute('placeholder','password');
};
$grid->getInlineAdd()->onSubmit[] = function($values) {
		(...)

tak pak změna perPage nefunguje a hlásí, že jsou pole povinná. Musím nejdříve něco do polí zadat a pak to již funguje.

Z nějakého důvodu to zkrátka validuje formulář na přidání pole při změne počtu zobrazených řádků.

japijana
Člen | 11
+
0
-

@pavel.janda vdaka za vyborny datagrid, pri inline editacii som narazil na spravanie, kedy v pripade, že je column hidden, tak sa neprenasa jeho hodnota, no v ramci ‚$values‘ je tento hodnota tohoto column prazdny string, je to tak schvalne ?

Pavel Janda
Člen | 977
+
0
-

Pardon, byl jsem od pc pár dní pryč, tak pojďme na to.

@exquis
1, Úplně nevím, kdy tato situace může nastat. Mohl bys připravit sandbox, kde by se toto chování projevovalo? Nebo na to narazil ještě někdo jiný? Jakou verzi datagridu používáš?

2, Vím, o co se jedná. Ano pravda, nemuselo by to házet exception. Stačilo by unsetnout hodnotu ze session. Píši si.

@Hlava
Jakou verzi používáš? Na webu dokumentace (ublaboo.org) to jede v pohodě, pokud dobře chápu tvojí situaci.

@japijana
Jaké jiné chování tě napadá? Nevím, zda by se vůbec měl pár klíč-hodnota odstranit z odeslaných $values. Ty jsi tam ten klíč vytvořil při registrace formulářového pole, tedy by se to tam mělo objevit.

Hlava
Člen | 19
+
0
-

@PavelJanda

ublaboo/controls          v1.0.2 Extension for Nette Framework: Controls: that has not translatable content (radiolist, selectbox), custom label text input
ublaboo/datagrid          v4.4.1 DataGrid for Nette Framework: filtering, sorting, pagination, tree view, table view, translator, etc
ublaboo/responses         v1.0.4 Additional responses for Nette Framework
Hlava
Člen | 19
+
0
-

@PavelJanda Snad jen ještě info, že mě to nepustí na žádné další akce, kde je potřeba něco vyplňovat do formulářů. Zkrátka to validuje všechny formuláře, místo jen toho, co je potřeba.

Rád poskytnu cokoliv, můžu ukázat celý kód, jestli to pomůže..