DataGrid
- phx
- Člen | 651
Tak jsem na srazu prislibil tak zverejnuji svuj DataGrid. No i kdyz je to kapku priohnuty puvodni Daviduv.
- Demo: http://nette.phx.cz/DataGrid/
- Download: http://nette.phx.cz/…Grid-1.0.zip
Jediny problem je ze to nefunguje AJAXove. Nemel jsem zatim cas to podrobne prozkoumat. Obecne s AJAXem v Nette si hraji par dni.
Dalsi vec co nejde je vykresleni paginatoru vicekrat (pod a nad tabulkou). Jako ono to jde, ale pri AJAXu to zlobi (2× stejne ID ve strance, coz neni Validni). Teoreticky neni problem ID nejak cislovat, ale ohledne AJAXu uz tapu.
Nevim zda mam psat ci nejak vice popisovat pouziti. Z prikladu je to snad jasne ne? Kdyztak se ptejte.
Rad bych nejakou odezvu. Napr kdo to kolikrat pouzil atd. co se mu libi a co by zmenil.
- phx
- Člen | 651
Razeni dle vice sloupku jsem umyslne deaktivoval. Je to, v PHP polsany kde jsem co menil + CSS ohledne sipecky. Osobne mi to prijde neuzivatelsky. Chci napr radit dle neceho jineho a musim 2× kliknout na to co se zrovna radi (obracene → deaktivovat) a pak az na to co chci.
Jineho je to, ze to nevypisuje DS, ale jen definovane sloupecky s popisky. Tz ze nazvy nejsou z DB, ale definovany tebou. (v praxi se to snad jinak nepouziva). Dale podpora sloupecku BEZ razeni, a skryte sloupecky (napr PK radku) a prazdne sloupecky (navaznost na callback dale). Dale muzes zaregistrovat callback pro konkretni sloupecky, kde data urcena do sloupecku upravis dle svych predstav. (napr: checkbox, img tuzky, true/false ⇒ ANO/NE)
A nazaver onen JS co podbarvuje radky pri prejezdu mysi, a pri zaskrtnuti checkboxu. Je to univerzalni a nezavisle na DG. Jen tomu reknes ID tabulky a na kolikaty checkbox na radku reagovat (pokud by jich tam bylo vice).
- raketoplan2005
- Člen | 147
Ahoj, vypadá to krásně, ale bohužel nejsem schopen to naimplementovat. I když udělám úplně čisté nette, kde dám jen tuten vzorový příklad, skončím na:
Notice: Undefined property: stdClass::$escape in /localhost/document_root/test/app/temp/cache-Nette.Template%0041002234ac0a45e6fb300f9cfb02244d1.grid.phtml.php on line 43
Fatal error: Method name must be a string in /localhost/document_root/test/app/temp/cache-Nette.Template%0041002234ac0a45e6fb300f9cfb02244d1.grid.phtml.php on line 43
pod čímž se mi zobrazí prázdná tabulka.
Můžete mi prosím poradit „how to“? Díky
- raketoplan2005
- Člen | 147
Zdrojáky jsou originální, kompletně beze změny, pouze doplněny o nette a dibi + změněna cesta v bootstrapu.
PHP: 5.2.6
Nette+dibi: Poslední stable
Editoval raketoplan2005 (24. 4. 2009 13:36)
- Honza Kuchař
- Člen | 1662
PetrP napsal(a):
phx napsal(a):
… 2× stejne ID ve strance …
Jen připomínám davidovi že to v sobotu chtěl řešit.
Nevím jestli jste to už vyřešili, ale já to vyřešil nádledovně
(funguje i s AJAXem) (můžu si tam těch paginatorů vyrenderovat kolik chci
:) )
Používám dataGrid co tu byl na ukázku s jQuery.
jde o to, že paginatory pojmenuju jako paginator1 až paginatorN
Tzn.:
class DataGrid extends Control
{
...
/** @var int */
protected $paginatorCount = 1;
...
public function renderPaginator()
{
...
$template->snippetName = "paginator".$this->paginatorCount;
...
}
...
}
v šabloně:
{snippet $snippetName}
...
{/snippet}
Pokud jsem na něco zapomněl, postnu někam celej zdroják. ;)
- phx
- Člen | 651
raketoplan2005 napsal(a):
Zdrojáky jsou originální, kompletně beze změny, pouze doplněny o nette a dibi + změněna cesta v bootstrapu.
Ted jsem to testoval s nette a dibi z SVN a vse je OK. Tak nevim. Posli zdrojaky…
honzakuchar napsal(a):
Nevím jestli jste to už vyřešili, ale já to vyřešil nádledovně (funguje i s AJAXem) (můžu si tam těch paginatorů vyrenderovat kolik chci :) ) Používám dataGrid co tu byl na ukázku s jQuery. jde o to, že paginatory pojmenuju jako paginator1 až paginatorN
Vim o tom. Toto reseni jsem navrhoval na minule PS. Je to nouzovka a sam veliky David se vyjadril, ze by to chtelo resit nejak komplexneji. Ale do te doby asi jina moznost neni.
- mkoubik
- Člen | 728
Jelikož vždycky zobrazuji paginator jenom nad, nebo pod tabulkou, tak jsem to „vyřešil“ následovně:
- Tabulka i paginator(y) jsou v jednom snippetu
- Renderuje se pomocí:
<?php
$grid->render(DataGrid::TOP | DataGrid::BOTTOM);
//nebo:
$grid->render(DataGrid::BOTH);
//apod
?>
- Zároveň pokud se nezobrazí ani jeden paginator, tak se automaticky vypne stránkování.
- romansklenar
- Člen | 655
Malá ochutnávka mého DataGridu před vydáním jak jsem na PS slíbil, stay tuned!
- vlki
- Člen | 218
Myslím, že by to mohlo mít trochu tvrdší validaci parametrů, aby se pak toho pak nevyužívalo k nějakému byznysu:)
http://demo.datagrid.romansklenar.cz/?…
by se třeba mělo přesměrovat na
http://demo.datagrid.romansklenar.cz/?…
Editoval vlki (17. 5. 2009 11:15)
- Tomik
- Nette Evangelist | 485
Jak jsem již psal na Twitteru, naprosto skvělá práce!
Jen takový malý dotaz: jde nějak nastavit, zda bude možné řadit pouze podle jednoho sloupce (tak jak to má ve svém DG phx) nebo podle více sloupců, tak jak to je v těch příkladech.
Jinak co se týče toho „prázdného řádku“ s inputy pro vkládání
nových položek, myslím, že by to udělat šlo, jen by uživatel nastavil,
jakou metodou, v jaké třídě se mají data z formuláře zpracovat… něco
jako $datagrid->handleNewRow = 'PagesModel::newPage';
. A takhle
fce by byla jen předaná formuláři, který bys (pokud by to bylo nastavené)
generoval do toho prázdného řádku. Jasně, není to nic složitého, a dá
se to jednoduše dodělat, ale bylo by fajn, kdyby to ten DG uměl sám. ;)
- romansklenar
- Člen | 655
vrtak-cz napsal(a):
A jak to vydíš s vydáním? Daří se profilování?
No já nevím, co myslíte, schválně jsem tam nechal profiler ať jde vidět čas, pohybuje se to okolo 150~300ms. Ale localhostu pouze s čistým apachem mi to běhá i 10× déle.
vlki napsal(a):
Myslím, že by to mohlo mít trochu tvrdší validaci parametrů, aby se pak toho pak nevyužívalo k nějakému byznysu:)
Zas nějak moc to hrotit nebudu, všechny chybové stavy jsou snad ošetřeny a na vstupní hodnoty slouží inputy :)
Tomik napsal(a):
…
Je tam něco jako $grid->multiOrder
čím se to dá vypnout
(default je zapnuto).
S těmi inputy na nový řádek je to takové ošemetné: vazba na model se
dá řešit tak jak píšeš, ale musí na to uživatel myslet + v té
přehledové tabulce nemusí být zobrazeny všechny sloupce taky (zase je
třeba na to myslet v modelu).
Ale klidně takový odvozený grid napíšu (počítám, že se jich objeví
i více časem), problém to snad nebude, grid má vlastní vykreslovač,
který se jen na jednom místě upraví a mimo jiné podporuje i manuální
vykreslení jako formuláře:
{? $grid->render('begin')}
{? $grid->render('errors')}
{? $grid->render('body')}
{? $grid->render('end')}
// plus např.
{? $grid->render('paginator')}
{? $grid->render('info')}
Dopíšu k tomu nějaké how-to a celou tu demo aplikaci i grid zvlášť pak hodím tady do repozitáře komponent. Nejspíš v úterý k večeru by to tam mohlo být.
EDIT: a co se týče definice, bylo to psáno s důrazem na to aby člověk nemusel kvůli dosažení nějaké malé úpravy např. ve formátování hnedka dědit a přepisovat, takže se s tím dá docelá vyhrát.
Od jednoduchých gridů: (1. example)
$model = new DatagridModel('customers');
$grid = new DataGrid;
$grid->bindDataTable($model->getCustomerAndOrderInfo());
// if no columns are defined, take all cols from given data source
$this->addComponent($grid, 'baseGrid');
Až po takovéto plně customiznuté: (3. example)
$model = new DatagridModel('customers');
$grid = new DataGrid;
$translator = new Translator(Environment::expand('%templatesDir%/customersGrid.cs.mo'));
$grid->setTranslator($translator);
$renderer = new DataGridRenderer;
$renderer->paginatorFormat = '%input%'; // customize format of paginator
$grid->setRenderer($renderer);
$grid->itemsPerPage = 10; // display 10 rows per page
$grid->bindDataTable($model->getCustomerAndOrderInfo());
$grid->multiOrder = FALSE; // order by one column only
$operations = array('delete' => 'delete', 'deal' => 'deal', 'print' => 'print', 'forward' => 'forward'); // define operations
$callback = array($this, 'gridOperationHandler');
$grid->allowOperations($operations, $callback, 'customerNumber'); // allows checkboxes to do operations with more rows
/**** add some columns ****/
$grid->addColumn('customerName', 'Name')->addFilter();
$grid->addColumn('contactLastName', 'Surname')->addFilter();
$grid->addColumn('addressLine1', 'Address')->getHeaderPrototype()->style('width: 180px');
$grid->addColumn('city', 'City')->addSelectboxFilter();
$grid->addColumn('country', 'Country')->addSelectboxFilter();
$grid->addColumn('postalCode', 'Postal code')->addFilter();
$caption = Html::el('span')->setText('O')->title('Has orders?')->class('link');
$grid->addCheckboxColumn('orders', $caption)->getHeaderPrototype()->style('text-align: center');
$grid->addDateColumn('orderDate', 'Date', '%m/%d/%Y')->addDateFilter();
$grid->addColumn('status', 'Status')->addSelectboxFilter();
$grid->addNumericColumn('creditLimit', 'Size', 0)->addFilter();
$grid['addressLine1']->addFilter();
$grid['orders']->addSelectboxFilter(array('?' => '?', '0' => "Don't have", '1' => "Have"), TRUE);
/**** column content affecting ****/
// by css styling
$grid['orderDate']->getCellPrototype()->style('text-align: center');
// by replacement of given pattern
$el = Html::el('span')->style('margin: 0 auto');
$grid['status']->replacement['Shipped'] = clone $el->class("icon icon-shipped")->title("Shipped");
$grid['status']->replacement['Resolved'] = clone $el->class("icon icon-resolved")->title("Resolved");
$grid['status']->replacement['Cancelled'] = clone $el->class("icon icon-cancelled")->title("Cancelled");
$grid['status']->replacement[''] = clone $el->class("icon icon-no-orders")->title("Without orders");
// by callback(s)
$grid['creditLimit']->formatCallback[] = 'TemplateHelpers::bytes';
/**** add some actions ****/
$grid->addActionColumn('Actions')->getHeaderPrototype()->style('text-align: center; width: 98px');
$icon = Html::el('span');
$grid->addAction('Copy', 'Customer:copy', clone $icon->class('icon icon-copy'));
$grid->addAction('Detail', 'Customer:detail', clone $icon->class('icon icon-detail'));
$grid->addAction('Edit', 'Customer:edit', clone $icon->class('icon icon-edit'));
$grid->addAction('Delete', 'Customer:delete', clone $icon->class('icon icon-del'));
$this->addComponent($grid, 'customersGrid');
- Honza Marek
- Člen | 1664
Pokusím se ti aspoň zaktualizovat ten ajaxový plugin pro jQuery než to vydáš :)
- LuKo
- Člen | 116
Výborná práce! K dokonalosti už chybí jen skrývatelné sloupce – mám tabulku s 50 sloupci a chci zobrazit jen některé. To, které se zobrazí, mám možnost ovlivnit flexibilně přímo na stránce, nikoli natvrdo v kódu. Ve filtrovacím řádku by možná přišla vhod možnost zvolit rozsah hodnot, ale to už je příliš komplikované. Hezky to má vyřešené Jakub Vrána v PhpMinAdminu.
- romansklenar
- Člen | 655
LuKo napsal(a):
Výborná práce! K dokonalosti už chybí jen skrývatelné sloupce – mám tabulku s 50 sloupci a chci zobrazit jen některé. To, které se zobrazí, mám možnost ovlivnit flexibilně přímo na stránce, nikoli natvrdo v kódu. Ve filtrovacím řádku by možná přišla vhod možnost zvolit rozsah hodnot, ale to už je příliš komplikované. Hezky to má vyřešené Jakub Vrána v PhpMinAdminu.
U NumericColumn
-ů funguje filtrování pomocí
>, >=, =, <>
apod (link).
Můžeš mi ty skrývatelné sloupce ještě trochu víc rozepsat? Klidně i do mailu. Dokážu si představit všechno, až na to jakým způsobem sloupec znovu zviditelním.
EDIT: inspirován datagridem, který používá google na svém googlecode už mám bližší představu :)
Honza M. napsal(a):
Pokusím se ti aspoň zaktualizovat ten ajaxový plugin pro jQuery než to vydáš :)
Právě jsem si říkal, že už bych mohl upgradenout :) ten nový způsob jsem totiž ještě nezkoušel.
Editoval romansklenar (30. 5. 2009 22:20)
- romansklenar
- Člen | 655
phx napsal(a):
…I kdyz asi bude kapku rychlejsi:)
O něco je. Udělal jsem demo aplikaci se stejnou strukturou jako je na tvém demu a zprůměroval doby běhu celé app co údává profiler a průměrný výsledek je ~540ms vs. ~620ms. Samozřejmě čím složitější (množství filtrů, akcí/generování linků, apod.), tím delší bude vykreslování. Původní implementace ale byly dost pomalé, teď už snad moc slabých míst není.
Jen bych jeste dodelal pro filtrovani podporu * jako zastupny znak!
Nojo podpora pro regex se mi někde vytratila :)
Kdy to bude verejne?
V průběhu dneška snad už :)
- romansklenar
- Člen | 655
Tak zdrojáky celé demo aplikace z http://demo.datagrid.romansklenar.cz můžete stahovat buďto z SVN repozitáře nebo přímo z archívu.
Se spuštěním by snad neměly být žádné problémy, je to all-in-one pack obsahujíci i současné poslední revize Nette a dibi. Všem dobře známá vzorová databáze birt z tutoriálu je přítomna i jako MySQL dump + databázích SQLite 2 a 3, takže je možnost výběru (viz adresář models).
Nějaký ten pokec sepíšu do dokumentace zítra (EDIT: no vlastně už dneska :)). Tak testujte, reportujte :) Enjoy!
- romansklenar
- Člen | 655
Tak je to zdokumentováno, snad se tím vysvětlí případné nejasnosti pokud nějaké byly :)
PS: Mám ten Translator hodit do Extras zvlášť?
- jasir
- Člen | 746
romansklenar napsal(a):
Tak je to zdokumentováno, snad se tím vysvětlí případné nejasnosti pokud nějaké byly :)
PS: Mám ten Translator hodit do Extras zvlášť?
Hmmm, ještě jednou veliké díky, fakt perfektní práce!!! I ta
dokumentace je špica!!!
Co se týče to ho Translátoru, jsem pro to ho tam dát zvlášť.
Editoval jasir (22. 5. 2009 20:44)
- romansklenar
- Člen | 655
Časem :) nejprve je třeba z bety udělat alespoň RC a dostatečně to prověřit, taky mě zajímá, jak se vám to zdá s rychlostí? Ikdyž je DataGrid primárně určen do administrací, kde nebude taková zátěž, mám pocit že tady bude ještě prostor ke zlepšování.
Pokud by to nevadilo, tak jelikož vznikla už i samotná stránka diskuze provázána přímo s dokumentací, tak bych přesunul diskusi přímo tam a téma uzavřel. Přece jen se to líp bude dohledávat novým lidem.