ublaboo/datagrid: mocný, rychlý, rozšiřitelný, hezký, anglicky dokumentovaný datagrid
- Pavel Janda
- Člen | 977
@Mart78 Zkus někam picnout zip toho projektu. Nebo na github třeba, pak to smažeš.
- Pavel Janda
- Člen | 977
@Mart78 Zkus mrknout do config.local.neon, jestli si tam náhodou nepřepisuješ databázi.
- Pavel Janda
- Člen | 977
@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 Option
s,
potom takto:
$grid->getColumn('status')->getOption(2)->setClass('btn-primary');
- David Kregl
- Člen | 52
Ahoj @PavelJanda
Nejprve bych Ti chtěl poděkovat za datagrid, který je konečně awesome! Mám
dvě otázky:
- 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ů)
- 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
@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
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
@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
@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
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;
}
- fizzy
- Backer | 49
@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
@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
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)
- Pavel Janda
- Člen | 977
@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
@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
@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
@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
@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
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
@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
@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
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
@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
@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
Ahoj libi se me tento grid ale zasekl jsem se na par vecech.
- Jak lze pridat attribut na action button aby se otevrela akce v novem okne?
- 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
@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
@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
@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..
- Pavel Janda
- Člen | 977
@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.
- Pavel Janda
- Člen | 977
Nová verze – v4.4.0
- Přidán NextrasDataSource (docu), @igor.pocta , @DavidKregl :)
- Pavel Janda
- Člen | 977
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
Nevím jestli jsem sám, kdo to řeší, ale občas mi blbne setDefaultSort();
Vypozoroval jsem 2 stavy:
- 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í
- 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
@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ů.
- Pavel Janda
- Člen | 977
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
@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