ublaboo/datagrid: mocný, rychlý, rozšiřitelný, hezký, anglicky dokumentovaný datagrid
- Hurass
- Člen | 114
@PavelJanda jak přesně funguje předání proměných šabloně?
Vytvářím akci:
$grid->addAction("edit")
->setTemplate(self::BASE_ACTION_TEMPLATE, array(
"class" => "btn btn-sm btn-default",
"icon" => "edit",
"link" => "User:edit",
"title" => "Edit",
));
V šabloně předpokládám, že by to mělo jít využít nějak takto:
<a href="#" class="{$class}">
<i class="fa fa-{$icon}"></i>
{$title}
</a>
Bohužel to nefunguje, nezná to ani jednu z těch proměnných, které jsem šabloně poslal.
Editoval Hurass (21. 2. 2016 13:20)
- Pavel Janda
- Člen | 977
@Hurass funguje to zatím jen u sloupců, nikoliv u akcí. Přidám, dej mi chvíli.
- Pavel Janda
- Člen | 977
Je možné skrýt select box s výběrem počtu záznamů na stránku? Nerad bych to řešil v css, prostě bych chtěl, aby se to vůbec nevykreslovalo.
Lze nastavit custom šablona a přepsat block #pagination.
- David Grudl
- Nette Core | 8218
Ahoj Pavle, zkouším teď na jednom projektu tvůj DataGrid. Moc se líbí, jak poctivě má zpracovanou dokumentaci.
Při prvních krůčcích jsem se nicméně na pár věcech vypekl nebo je musel zkoumat, tak jsem je sepsal. Neber to prosím jako kritiku, spíš jako výsledek user testingu, který může datagrid ještě více zpřístupnit nováčkům.
- na stránce overview:
- chybí informace, jak se instaluje přes composer (tj. název balíčku, lze zjistit až prokliknutím na github)
- assety: není úplně jasné, k čemu jsou potřeba, bez kterých se mohu
obejít a v jakém pořadí je načítat, dále zda nette.ajax.js vyžaduje
i nějaké rozšíření (a asi i zmínit nutno volat
$.nette.init()
) - asi by se hodily i odkazy, třeba happy.js neznám, web http://happyjs.com/ se kterým možná souvisí nefunguje, soudě podle analýzy standalone.js to tohle asi nebude. Zdroják by asi mohl být i v distribuci. Stejně tak v případě Bootstrap Datepicker je potřeba použít tento a nikoliv tento
- chybí informace, že potřebuje CSS z Boostrap
- chybí informace, že potřebuje Font Awesome
- drobnost: v textu je špatný odkaz na stránku data source (datadource)
- v ukázkovém kódu (Show me the code) by bylo fajn připomenout, že třída je Ublaboo\DataGrid\DataGrid (komentářem? nebo použít celý název?)
- pod kódem je i zdroják šablony grid.img.latte, ale chybí další v kódu uvedené šablony. Je to někde na githubu?
- na stránce data-source by mělo být zmíněno, že setPrimaryKey() je nutné volat před setDataSource() (asi by to mohl čeknout i datagrid)
- na stránce column
- je ten datagrid fakt příliš dlouhý
- místo
$column = $title
by mělo být$column = $key
- na stránce filter
- není vysvětlené, k čemu je $name u filtrů (btw, nebylo by lepší API
addColumnText()->addFilter(...)
?)
- není vysvětlené, k čemu je $name u filtrů (btw, nebylo by lepší API
Dál jsem se ještě nedostal. Každopádně dobrá práce!
- Pavel Janda
- Člen | 977
@DavidGrudl Děkuji za reakci a úhel pohledu z této strany.
Opravdu jsem na to zanevřel. Tak nějak předpokládám, že všichni automaticky zkoumají kód a se vším si poradí. Což není pravda a napravím to.
Abych zodpověděl některé body:
- happy je miniknihovnička (momentálně zde) pro „zkrášlení“ radio/checkbox inputů. Žádné závislosti (tedy, je potřeba html5 a CSS3).
To je vlastně všechno, zbytek nejsou otázky. :)
Zkusím stihnout zdokonalit dokumentaci dřív, než stihneš projít další stránky.
Editoval Pavel Janda (21. 2. 2016 23:39)
- Pavel Janda
- Člen | 977
Nová verze – v2.0.0
- Přidán bower balíček
ublaboo-datagrid
– více info o assetech zde (BC break) - Možnost vyhodit „all“ z items_per_page listu
- Stringy k překladu jsou nyní vedené v tečkové notaci (possible BC break)
ActionCallback
– akce rovnou na user callbackDoctrineDataSoruce
: Práce s defaultními aliasy tabulek (není již třeba uvádět pro každý sloupec/filtr sloupec s aliasem znovu)- Standalone.js is no longer created within this repo (BC break)
- Opravy
Děkujeme všem za PR, issues a další připomínky!
Editoval Pavel Janda (23. 2. 2016 15:31)
- hury
- Člen | 56
Ahoj, zkousim tvuj datagrid, vypada to pekne…
predem diky za odpoved :-)
(pouzivam nette/database)
ale nejak jsem nepochopil, jak pouziju sloupec z jine tabulky, aniz bych
musel pouzivat joiny…
v o5/grido je toto reseno velmi jednoduse
$grid->addColumn('users_skupina.nazev', 'Členem')
table users:
id | username | users_skupina_id |
---|---|---|
1 | abc | 1 |
2 | eee | null |
3 | Drak | 2 |
table users_skupina:
id | nazev |
---|---|
1 | Nicky |
2 | Borci |
Druha otazka:
jde nejak udelat externi filter? Aby nebyl vypsany u policek :-)
Editoval hury (23. 2. 2016 13:14)
- Pavel Janda
- Člen | 977
@hury 2, $grid->setOuterFilterRendering()
, je to v docu.
1, Neznám Grido do detailu, ale předpokládám, že s tím ti pomohla spíš NDBT než Grido. Když uděláš něco takového, tak by ti to mohlo vypsat požadovaná data:
$ndb->table('users')->select('users.*, : users_skupina.nazev')
Zkus to – ale spíš jsem to tak střelil od boku. Doufám chápeš moji pointu.
Je ale možné, že s tím Grido dělá nějaká kouzla, podávám se. :)
Editoval Pavel Janda (23. 2. 2016 14:05)
- Pavel Janda
- Člen | 977
@hury Zkusil jsem tvůj příklad na o5\gridu a chová se to stejně. Musíš si nějakým způsobem definovat tu referenci, žádná kouzla se nedějí.
- hury
- Člen | 56
Diky, ten outerFilter jsem uplne prehledl…
externi data jsem udelal pres
->setRenderer(function($item){
if ($item->skupina_id !== null) {
return $item->skupina->nazev;
}
else {
return '-';
}
});
mozna jsem jen ovlivnen vice gridy, posledni dobou zkousim vse mozne a nemuzu najit neco co budu pouzivat. Ten tvuj je na dobre ceste :-)
nejaka myslenka, jak udelat toto?
ruzne barevne tlacitka, pokud je $item aktivni, ci nikoli
$grid->addAction('detail','')->setIcon('search')->setClass(function($item){
if ((int)$item->aktivni === 1) {
return 'btn btn-xs btn-success';
}
else {
return 'btn btn-xs btn-danger';
}
});
pak jeste jedna otazka:
potrebuji udelat filterSelect, kde filtruji nad ruznymi sloupci…
(kazda hodnota ma ruzny WHERE …)
polozky selectu: vse, nove, stare, propadle
vse = zadne omezeni...
nove = tabulka.aktivni = 1 && tabulka.datum > '2016-01-01'
stare = tabulka.datum < '2016-01-01'
propadle = tabulka.aktivni = 0 && tabulka.stav = 'abc...'
je to jen priklad, takovy select by bala asi kravina :-)
- Pavel Janda
- Člen | 977
@hury
1, Jasně, taky to tak jde. Pokud bys chtěl, aby ti ta NDBT udělala join, tak
zkus ten můj příklad, mně fungoval na stejné struktuře, jakou jsi psal.
:) – Ale jak říkám, za to může NDBT, ne gridy.
2, Momentálně můžeš takovýmto callbackem ovlivňovat třídu celé ROW (viz – dole – Row Callback). Ale líbí se mi určování title, class, confirm a podobně callbackem, dávám do issues a hned večer napíšu.
3, Definuj si vlastní podmínky filtru:
$grid->addFilterSelect('status', ['....'])->setCondition(function($fluent, $value) {
switch ($value) {
case 'vse':
break;
case 'nove':
$fluent->where('...')
break;
case 'stare':
$fluent->where('...')
break;
}
});
Editoval Pavel Janda (23. 2. 2016 15:52)
- Pavel Kravčík
- Člen | 1195
@PavelJanda: Nová verze vypadá super. Ty překlady jsou mnohem lepší takhle.
Chvíli mi trvalo dát do kupy JS (jsem nicka – nepoužívám
balíčkovač na JS, jen composer). Všiml jsem si jen dvou drobností u
item-detail
.
V minulé verzi fungoval bez jquery-sortable(), to je asi úplně nepodstatné. Jen mi překvapila ta závislost navíc.
A když definuji grouped-action a vyberu vše a následně kliknu na „eye-icon“ pro zobrazení detailu, tak se řádek odoznačí. Zkoušel jsem na lokále i na demíčku. Asi by bylo lepší, kdyby zůstal řádek označený.
- Pavel Janda
- Člen | 977
@PavelKravčík item-detail nefunguje bez jquery sortable? To bych se divil. Tenhle scirpt je tam jen kvůli sortění tabulky a tree view, ale nemá co do činění s item detailem. Mrknu na to.
Teď se posílá snippet a překreslí se jak položka, tak detail položky. Ta položka se posílá zbytečně. Super, píšu si, dík.
Edit
Assety: No já jsem taky backenďák. Pravda ale je, že to usnadňuje závislosti.. Tak jsem se k tomu dokopal. Kdo si s tím nebude vědět rady, snad to vykouká z cest assetů v dokumentaci.
Editoval Pavel Janda (23. 2. 2016 15:59)
- Pavel Janda
- Člen | 977
v2.0.2 opravuje oboje – Není třeba jquery sortable, pokud nechci sortit a neposílá se v xhr response item row.
- Pavel Kravčík
- Člen | 1195
@PavelJanda:
A ještě zmizí checkbox. Ale nijak hlouběji jsem netestoval.
EDIT: To je fofr, skvělá práce!
EDIT2: Nasazeno a „working like a charm“. :)
Editoval Pavel Kravčík (23. 2. 2016 16:29)
- Pavel Janda
- Člen | 977
@PavelKravčík DataGrid použivá mojí miniaturní library happy
(bower install happy
), která dělá ty pěkné checkboxy.
Includuješ scripty té knihovničky? Pokud bys je nehctěl používat, lze je
vypnout: $grid->useHappyComponents(FALSE)
.
- Pavel Kravčík
- Člen | 1195
@PavelJanda: Jasně, používám, je to pěkné. Našel jsem si to podle odpovědi na D.Grudla, ale přemýšlel jsem zezačátku, jestli neudělat vlastní šablonu a dát tam to současné řešení, které mám na „hezké“ checkboxy. Každopádně tenhle doplněk je paráda.
Ještě jeden nedostatek tu vidím: Absenci donations. :)
- Pavel Janda
- Člen | 977
@PavelKravčík Hehe, nejlepší donations jsou do kódu. :)
Možná tam nějaké tlačítko přidáme. :)
- Pavel Kravčík
- Člen | 1195
@PavelJanda: Na to musí být člověk dobrý programátor a kamarádit se s Gitem. :) Já si frčím v SVN a nemám důvod přecházet. GitHub mám jen na hvězdičkování Nette-doplňků.
- Pavel Janda
- Člen | 977
@hury Chyba.
A teď: fix je jednoduchý, přidám řádek
$form->setTranslator($this->getTranslator());
. Jenže takhle
se budou překládat i select boxy. Musím se rozhodnout, jestli se budou
překládat i options selectů..
- hury
- Člen | 56
toto me stve i u formulare…
reseni se mi vubec nelibi (ale treba to delam blbe, a jde to lepe :-))
$form->setTranslator($this->translator);
$form->addText('aresIc', 'sign.form.ic', 12, 20); // tady je to v pohode...
$form->addSelect('aresZeme', $this->translator->translate('sign.form.zeme'), $seznamZemiSelect)
->setTranslator(null) // kvuli seznamu zemi - aby se to neprekladalo
->setPrompt($this->translator->translate('sign.form.vyberte'));
nejake elegantnejsi reseni by bodlo… neco jako:
$form->addSelect('aresZeme', 'sign.form.zeme', $seznamZemiSelect)
->translateLabel()
->translateOptions(false)
->translatePrompt();
- Pavel Janda
- Člen | 977
Poradim ti asi lepsi reseni. Koukni se do ublaboo/controls. Je am select, kteremu se neprekladaji opions. A je tam i stejne fungujici NotTranslatableRadioList.
Editoval Pavel Janda (23. 2. 2016 17:43)
- Hurass
- Člen | 114
Mám jeden problém s řazezím na joinované tabulky. Používám Kdyby/Doctrine. Konkrétně vypisuju data z tabuky user která má vazbu n:1 na tabulku user_role.
Třída App\ModelUser:
/**
* @ORM\ManyToOne(targetEntity="UserRole", inversedBy="users", cascade={"persist"})
*/
protected $userRole;
Ukázka jak tvořím grid:
$grid->setDataSource(
$this->userRepository->createQueryBuilder("u")
->leftJoin(\App\Model\UserRole::class, "ur", \Kdyby\Doctrine\Dql\Join::WITH, "ur.id = u.userRole")
);
$grid->addColumnText("role", "Role", "ur.name")
->setSortable();
Vypíše se vše v pořádku, řadit jde podle všech slouplců, ale né
právě Role, která je $name
ve tříde
App\Model\UserRole
.
Při pokusi seřadit data podle role se vygeneruje DQL:
SELECT u
FROM App\Model\User u
LEFT JOIN App\Model\UserRole ur WITH ur.id = u.userRole
ORDER BY u.ur.name ASC
Předpokládám, že by to mělo být takto:
SELECT u
FROM App\Model\User u
LEFT JOIN App\Model\UserRole ur WITH ur.id = u.userRole
ORDER BY ur.name ASC
Poradí mi někdo, jak toho docílit?
- Pavel Janda
- Člen | 977
Nová verze – v2.1:
- Možnost definovat icon, title, confirmation dialog a class
Column\Action
callbackem - DataGrid::setDefaultSort does not need a session in time anymore
- Fixy
Editoval Pavel Janda (25. 2. 2016 0:10)
- pitr82
- Člen | 121
Ahoj,
zkoušel jsem podle návodu (mimochodem pěkně dokumentovaný) Item Detail a
má dvě otázky.
- Nejde mi přistoupit k proměnné jako k oběktu $item->id ale jen přes pole $item[‚id‘]
- musím dvakrát kliknout pro rozbalení detailu.
Poprvé se provede ajax, ale nezobrazí se detail, podruhé už detail zobrazí.
- Pavel Janda
- Člen | 977
@pitr82
2, Zkoušíš to na existujícím projektu, nebo na sandboxu? Kdybys to zkoušel na nějakém sandboxu, tak to můžeš hodin na git a já se na to podívám.
Takhle tam může být chybka z více důvodů.
- Máš popořadě naincludované všechny scripty jako je to v docu? – Nehází ti console žádné errory?
- Používáš poslední verzi
DataGridu
– v2.1.1? - Jak stahuješ scripty? Přes bower?
Funguje ti správně demo na ublaboo.paveljanda.com/datagrid?
1, Mohl bys mi ukázat, jak máš napsanou celou component factory v presenteru? Jakou vrstvu mezi databází a aplikací používáš?
Editoval Pavel Janda (25. 2. 2016 14:20)
- Pavel Janda
- Člen | 977
@pitr82 :) Jsem rád, že je používán.
Co myslíš tím „ve stejné kvalitě“? Myslíš aby vypadaly podobně jako
ty checkboxy? Nebo se ti jen nepodařilo nahrát bootstrap-datapicker? Ten je
tam nyní normálně využit.
Kdyby to první, tak rovnou odpovím, že já určitě asi ne. :) Jsem primárně backenďák a nemyslím, že mám znalosti na to, abych napsal lepší..
- Pavel Kravčík
- Člen | 1195
@PavelJanda:
Co něco takového do další verze? Tj. správa hromadných akcí jako u obyčejných. Myslíš, že už je to trochu složitější oříšek. :)
$grid->addGroupAction('gruppen', Zaplatit smlouvy');
$grid->allowRowsGroupAction('gruppen', function($row)
{
return $row->status != \Psa\Entity\ImportEntity::STATUS_MANUAL;
});
- Pavel Janda
- Člen | 977
@PavelKravčík Jak by se se choval checkbox, pokud by byl
zaškrtnutý, po vybrání akce, která by nepodporovala vybrání vybrané
položky? :D To zní strašně, je to pochopitelné?
Nebo by se prostě tyto položky neodeslaly?
- Pavel Kravčík
- Člen | 1195
@PavelJanda: Jasně, tomu rozumím. Myslel jsem něco jako onChange[], kontrola jen vybraných a nějaký disable. Moc hezké to není, proto jsem to jen nadhodil, kdyby existovalo hezčí řešení. Na nějakém starém gridu jsem to někde měl. Ale nic pěkného to nebylo.
- exquis
- Člen | 83
Ahoj, mám problém s automatickým potvrzováním filtrů. Projevuje se to např.:
- ve filtru typu addFilterText(), když do něj kliknu a začnu psát slovo, tak se hned potvrdí a formulář se odešle aniž bych ho potvrdil a filtr se nezohlední
- u typu addFilterDate stačí kliknout do pole pro zadání data, vyběhne bootstrap datepicker, ale hned po jeho zobrazení se formulář opět sám odešle, aniž bych stihnul vybrat datum, je to prakticky ihned
JS a CSS mám načtené všechny, console žádnou chybu nehlásí, myslel jsem si, že se do toho nějak míchá liveValidation (konkrétně nastavené wait:150), ale to jsem dal na false a stejně to dělá dál
function createComponentObjednavky() {
$grid = new DataGrid();
$grid->setDataSource($this->Orders->getTblOrders()->getAll());
// Columns
$grid->addColumnDateTime("issue_date", "Datum vytvoření")->setSortable();
$grid->addColumnLink("order_number", "Číslo objednávky", "detailObjednavky")->setSortable();
$grid->addColumnDateTime("name", "Jméno")->setSortable();
// Filters
$grid->addFilterDate('issue_date', 'Datum vytvoření');
$grid->addFilterText('order_number', 'Objednávka');
return $grid;
}
{control objednavky}
EDIT: zdroje mám stažené skrze BOWER, takže ve špatných verzích by snad chyba být neměla.
Editoval exquis (28. 2. 2016 13:24)
- Pavel Janda
- Člen | 977
@exquis
- To je dost divné. Pravděpodobně ti do toho zasahují scripty třetích
stran nebo tvoje. Dal jsem na github v rychlosti testovací array-datagrid-sandbox,
kde se nic takového neděje a vše je přesně podle dokumentace. Stačí
akorát
composer update
abower install ublaboo-datagrid
. - Ano, to je pravda. Bohužel eventy tohoto typu nejsou v JS ideální na
100%. Momentálně se odesílá ajaxový request při každém
input::onChange
. A onchange v js znamená, že se pošle i v případě, že přejde input pouze do stavufocus
.
- Pavel Janda
- Člen | 977
@harmim
1, Protože jednodušeji nastavíš selectu datagridu přeložené options než
odebereš překládání. Představ si, že bych to překládal – jak bys
docílil toho, aby se překlady zrušily? Moc by to nešlo..
Kdy jsou potřeba nepřeložené selecty? Pokud jsi se s tím ještě nesetkal, tak například tehdy, pokud potřebuješ select jmen produktů, adres, jmen zákazníků, kódů zemí, telefonních čísel… – prostě veškerých dat, která bereš z databáze.
2, Ze stejného důvodu, z jakého nepřekládám ani hodnoty sloupců. Replacement je náhrada za hodnotu sloupce. A opět, vypíše se víceméně hodnota řádku databáze. Může to být jak číslo, tak text. Může to být text k překladu, nebo jenom poupravený text, který se překládat nemá.
Pokud potřebuješ překládat jedno či druhé, je třeba nejdřív vytvořit přeložený seznam a ten předat DataGridu.
- exquis
- Člen | 83
@PavelJanda ještě jsem narazil na drobnou chybku – jakmile vypisuješ data pomocí nette/database a máš spojených více tabulek, tak hlásí chybu, že existuje více sloupců „ID“ a že nemá jak spočítat záznamy, to se mi povedlo obejít, když jsem natvrdo změnil, aby nedělal COUNT nad ID, ale „*“
/**
* Get count of data
* @return int
*/
public function getCount() {
return $this->data_source->count("*");
}
- Pavel Janda
- Člen | 977
@exquis To doporučuji nechat na css. Jednotlivé sloupce jsou snadno
indetifikovatelné, každý má třídu col-<key>
.
Hm, to se mi sice nelíbí, ale pravděpodobně to tak budu muset udělat. Dík za tip, přidám.
Editoval Pavel Janda (2. 3. 2016 19:05)
- exquis
- Člen | 83
Pavel Janda napsal(a):
@exquis To doporučuji nechat na css. Jednotlivé sloupce jsou snadno indetifikovatelné, každý má třídu
col-<key>
.Hm, to se mi sice nelíbí, ale pravděpodobně to tak budu muset udělat. Dík za tip, přidám.
Už na to koukám, paráda, díky. I když myslím, že by bylo nebylo špatné udělat něco jako setWidth().. když si představím, že bych musel pro každý sloupec z rozsáhlejšího systému psát vlastní styl .. to by se pak hodilo v tu chvíli udělat v CSS třídy .col-width-10, 20, 30 atd a ty třídy pak jednotlivým sloupcům přiřazovat.
Jinak musím pochválit perfektní datagrid ;)
- Pavel Janda
- Člen | 977
@exquis Mně by se taky líbilo, kdyby to šlo takhle jednoduše. Napadá tě nějaký jiný nápad, než psát PHPčkem inline styly?
- Pavel Janda
- Člen | 977
@Šaman Tak by to jistě šlo. Tedy jich udělám 10. Jenže pak bude chtít někdo 15% šířku. Tak se přidá dalších 10. Pak bude chtít někdo 17,5%. :D Atp.
Bral bych to jako poslední možnost.