Gridito (falešný datagrid) – komponenta
- Honza Marek
- Člen | 1664
Falešný datagrid je budoucí konkurenční produkt k datagridu od Romana Sklenáře. A už se můžu pochlubit demem na http://griddemo.janmarek.net/document_root/.
- Honza Marek
- Člen | 1664
Mělo by to být hodně univerzální, ale zatím OrmionCollection, když se ptáš ;)
- Lopata
- Člen | 139
Honza Marek napsal(a):
Falešný datagrid je budoucí konkurenční produkt k datagridu od Romana Sklenáře. A už se můžu pochlubit demem na http://griddemo.janmarek.net/document_root/.
Proč to vyvíjíš „znova“? Ono je to postavené na PHP 5.3…?
- Honza Marek
- Člen | 1664
Lopata, despiq:
Můžete kouknout zhruba, jak se ten grid definuje: https://gist.github.com/346294
Oproti „velkému datagridu“ pro vlastní vykreslování buněk nebo vytvoření funkčních tlačítek potřebuju mnohem méně kódu. Nemusim definovat signály nebo zakládat šablony pohledům s formulářema na upravení či založení nového záznamu.
Dalším plusem mého řešení je témovatelnost pomocí jQuery UI a nezávislost na DibiDataSource.
Abych to shrnul, cílem není okopírovat kompletní funkčnost Romanova datagridu, ale abych já měl jednodušší práci, když budu vyrábět nějaké administrační rozhranní.
- Honza Marek
- Člen | 1664
Spokojen nejsem, ale teď jsem měsíc nebyl schopen naprogramovat ani čárku. Z velkejch věcí určitě budu potřebovat filtry a pak pár nějakejch detailů. Jinak nejsem moc spokojen s tím „CRUDem“. Když odešlu chybně vyplněný formulář a neodchytí to JS, tak přijdu o data. Ale tohle je bohužel koncepční, nikoliv implementační záležitost, takže řešení se musí vymyslet, nikoliv naklepat.
- v6ak
- Člen | 206
Aha, takže ve chvíli, kdy se ten token dostane do URL, přestává být citlivý, že? Pokud to dobře chápu, tak tím pádem se nemusím bát potenciálních odkazů ven z cílové stránky.
Ještě bych měl menší kritiku: mezi jednotlivá tlačítka by se hodilo nějaké whitespace, bez stylů to pak může bypadat jako jedno slovo, což není dobře.
- v6ak
- Člen | 206
Kromě DibiModelu bych to označil zatím spíše za experimentální. DibiModel ve starší verzi (pro PHP 5.2, neobsahuje create, neumí třídit a má natvrdo primary key ‚id‘) používám už i na ostrém webu a zatím OK.
Měl bych pár dotazů k implementaci:
- Gridito\IModel::setSorting(…) má počítat jenn s řazením podle jednoho sloupce?
- Má Gridito\IModel::setupGrid(Gridito\Grid) dělat i něco kromě nastavení primárního klíče?
Chtěl bych, aby se na mě sesypala kritika za Gridito\IEditableModel a použití ArrayAccess včetně návratových hodnot (vizte Gridito\DibiEditableModel). Je to ještě OK, nebo radši k tomu nemám ohýbat ArrayAccess a definovat vlastní metody? Anebo to mám udělat ještě jinak? Variantu použít IModel a k tomu nějaký IEditableRecord jsem zavrhl kvůli vetší volnosti, byl by k tomu potřeba ohýbat např. i Ormion, což nechci.
Měl bych drobnou výhradu k názvu IModel – možná by to mělo být spíše IRepository.
Dále bych měl určitou výhradu k tomu, že IModel je ohledně stránkování apod. brán jako mutable. To znamená, že je vpodstatě potřeba pokažé vrátit novou instanci.
Dále jsem proti generování ID v podobě ++$this->toolbarButtonId. Takto někomu pod rukama přehodím pořadí tlačítek (třeba zveřejnit vs. smazat) a je v háji. Asi by to chtělo explicitní uvádění id.
Pak bych měl i jedno řešení potenciálních problémů: Gridito mi nechtělo stránkovat. Zjistil jsem, že v @layout.phtml (víceméně původní ze skeletonu) je k {include #content} potřeba přidat zavináč.
V příkladu Ti chybí addProtection.
Jo, do názvu tématu PLS přidej i název ‚Gridito‘, třeba i „Gridito – Falešný datagrid – komponenta“.
- Honza Marek
- Člen | 1664
v6ak napsal(a):
Super,
Měl bych pár dotazů k implementaci:
- Gridito\IModel::setSorting(…) má počítat jenn s řazením podle jednoho sloupce?
Ano. Pro uživatele je řazení podle jednoho sloupce většinou lepší. Pokud budu implementovat řazení podle více sloupců, asi přidám metodu setMultiSorting nebo něco takového.
- Má Gridito\IModel::setupGrid(Gridito\Grid) dělat i něco kromě nastavení primárního klíče?
Můžeš si tam dělat co chceš. Slouží to k libovolné inicializaci komponenty.
Chtěl bych, aby se na mě sesypala kritika za Gridito\IEditableModel a použití ArrayAccess včetně návratových hodnot (vizte Gridito\DibiEditableModel). Je to ještě OK, nebo radši k tomu nemám ohýbat ArrayAccess a definovat vlastní metody? Anebo to mám udělat ještě jinak? Variantu použít IModel a k tomu nějaký IEditableRecord jsem zavrhl kvůli vetší volnosti, byl by k tomu potřeba ohýbat např. i Ormion, což nechci.
Neměl jsem čas to zatím prozkoumat, ale jinak bych asi ArrayAccess v tomhle případě nepoužil.
Měl bych drobnou výhradu k názvu IModel – možná by to mělo být spíše IRepository.
Proč?
Dále bych měl určitou výhradu k tomu, že IModel je ohledně stránkování apod. brán jako mutable. To znamená, že je vpodstatě potřeba pokažé vrátit novou instanci.
Asi nerozumím.
Dále jsem proti generování ID v podobě ++$this->toolbarButtonId. Takto někomu pod rukama přehodím pořadí tlačítek (třeba zveřejnit vs. smazat) a je v háji. Asi by to chtělo explicitní uvádění id.
Možná by to šlo nějak volitelně.
Pak bych měl i jedno řešení potenciálních problémů: Gridito mi nechtělo stránkovat. Zjistil jsem, že v @layout.phtml (víceméně původní ze skeletonu) je k {include #content} potřeba přidat zavináč.
Jasně, je to komponenta, která používá ajax.
Jo, do názvu tématu PLS přidej i název ‚Gridito‘, třeba i „Gridito – Falešný datagrid – komponenta“.
ok
- v6ak
- Člen | 206
Jé, já odpověď odložil a pak zasklil :-(
K setupGrid(): Jasně, jde mi o nějaké tipy na činnosti, které se zde
mohou nacházet. Popravdě řečeno, při implementaci DibiModelu jsem se díval
na OrmionModel.
ArrayAccess asi časem nahradím, asi to nebude velká změna. Ono mi to celkem
čisté přijde až na návratové hodnoty offsetSet. Jinak klíč null
u offsetSet není až takový výmysl, odpovídá to $foo []= bar.
K IRepository: http://www.phpguru.cz/…rstev-modelu – asi to není
vyloženě nutné, ale bylo by to asi lepší.
K mutable IModelu: pokud budu mít někde nějakou továrnu na IModel, musí
vždy vrátit novou instanci. Pokud by si instanci cacheovala, šlo by ji
v rámci kontextu továrny „rozbít“ (nechtěně ovlivnit vše) nějakým
setterem. Ale možná to takový problém není.
K id: Možná by bylo lepší za výchozí ID dosadit label, v případě
změny tu nejsou nějaké katastrofické následky moc pravděpodobné.
V případě přehození pořadí, řekněme, „Smazat“ a „Publikovat“,
je to mnohem horší.
Jinak jsem si všiml jedné vlastnosti, kterou nezmiňuješ: specifické
vykreslování typů \DateTime a boolean: https://github.com/…r/Column.php#L164
. To je důvod, proč v mém příkladu nefungují dva sloupce
(„Vytvořeno“ a „Je krásná“) korektně. Řešení mám v hlavě,
půjde o nějaký Decorator, aby jej bylo možné použít i mimo DibiModel.
V OrmionModelu to potřeba asi nebude, ale kdyby někdo chtěl třeba
NotORMModel, tak by se mu to mohlo hodit.
Mimochodem, zatím to skoro vypadá, jako by Gridito používali jen dva
programátoři (já a Honza). Můžete to někdo vyvrátit?
- Matúš Matula
- Člen | 257
Tiez nad tym momentalne uvazujem, ale som odkazany na php 5.2 . V6ak ako si na tom s tou automatizaciou Gridita pre php5.2? :-)
- v6ak
- Člen | 206
No, částečně. Napsal jsem https://gist.github.com/430117 (na
Windows jede pod Cygwinem), udělal pár ručních úprav (potřeboval jsem
honem funkční Gridito) a tím to skončilo. Doma asi napíšu nějaký lepší
skript. A pokud se budu nudit, implementuji i překlad anonymních funkcí na
třídy, takže půjde přeložit i EditableGrid apod. BTW: On ten trochu
lepší nástroj by mohl sloužit i k opačné portaci. A vlastně by se mi
to asi taky hodilo.
Jinak, vzpomínám si na tyto ruční úpravy:
- Přejmenování Button na Gridito_Button (kolize s \Nette\Forms\Button)
- Názvy tříd s tlačítky byly ve stringu, asi ve třídě Grid. Bylo z nich potřeba odstranit namespace.
- V nějakých renderovacích metodách tlačítek a asi i třídy Grid bylo potřeba se vyhnout použití method chainingu. Ale to jsem možná jen měl starou verzi Nette.
Pokud to chceš honem udělat, použij ten skript. Co bude potřeba dodělat, o to se PHP brzy přihlásí chybovou hláškou.
- Matúš Matula
- Člen | 257
Dik za bleskovu reakciu. Neponahlam sa s tym, teraz mam kopec roboty, len som si to chcel vyskusat :-)
- univerz
- Člen | 7
gratulujem k vykonnostne pouzitelnemu rieseniu datagridu. vidim, ze vyvoj na githube ide dopredu, je nejaka moznost, ze fork od v6ak bude zluceny pred tym, nez sa zdrojaky priliz rozidu?
k dokonalosti mi chyba (mozno som jej existenciu prehliadol) moznost nastavit si sirku jednotlivych stlpcov, v zaujme zachovania vykonu v klude pekne jednoucelova, bez vyuzitia Nette\Web\Html. pripadne by sa hodilo nieco na styl PositionColumn stareho datagridu, nech nie je nutne vsetko davat do buttonov. samozrejme, pokial nie su v dohladnej dobe planovane BC breaky, rad prilozim ruku k dielu :).
- v6ak
- Člen | 206
Já bych teď asi už začal na autoportaci pro PHP 5.2. Pak bych jednu nezveřejněnou třídu z 5.2 upravil pro 5.3. Pak bych měl asi nějak sloučit svůj fork a upravit všechny modely kvůli jednomu menšímu BC breaku – jak to na GITu udělat co nejčistěji?
Jinak BC breaky – nedávno byl jeden BC break v IModelu, ale nevím, jaké jsou další plány Honzy. Já navrhoval změnu identifikace tlačítek („Dále jsem proti generování ID v podobě ++$this->toolbarButtonId. Takto někomu pod rukama přehodím pořadí tlačítek (třeba zveřejnit vs. smazat) a je v háji. Asi by to chtělo explicitní uvádění id.“), která by sice bez BC breaku šla, ale bylo by to dost kostrbaté. Nechci se do toho pouštět sám, protože řešením bez Honzova souhlasu bych riskoval vývoj dvou vzájemně nekompatibilních větví.
<EDIT n=„1“>Jo, asi časem upravím trošku IEditableModel tak, aby nepoužíval ArrayAccess.</EDIT>
Šířka jednotlivých sloupců – zajímavá poznámka, mělo by jít stejně jako barvení sudých a lichých řádků (vlastní šablonou), ale bylo by možná vhodné mít příjemnější cestu. Nechceš přiložit ruku k dílu zde?
<EDIT n=„2“>Jo, ještě by bylo asi dobré vymyslet nějaký dobrý způsob, jak předávat šablonám parametry tak, aby:
- šlo využít nápověd IDE
- šablona mohla mít svoje specifické vlastnosti
- dědičnost nebyla zneužita
Co říkáte na toto?:
$grid->setTemplate(MyGreatGridTemplate::create()->setFoo(12)->setColumnSize('foo', '64px'));
Další věc je, že by se dalo toto nějak zakomponovat do Honzova návrhu o nastavení Gridita
v šablonách . Bylo by to cooler.
</EDIT>
Editoval v6ak (22. 9. 2010 8:37)
- univerz
- Člen | 7
v6ak napsal(a):
Co říkáte na toto?:$grid->setTemplate(MyGreatGridTemplate::create()->setFoo(12)->setColumnSize('foo', '64px'));
Další věc je, že by se dalo toto nějak zakomponovat do Honzova návrhu o nastavení Gridita v šablonách . Bylo by to cooler.
zrejme bude prezierave pockat si na vyjadrenie autora, kazdopadne som aj za variantu s quickfixom pomocou sablony – no idelane by som ju rad robil uz pre „spojene zrojaky“. aktualne robim s medziverziou s este vlastnou upravou pre namespaces a par upravami z gitu spred cca tyzdna.
- Werkov
- Člen | 17
- Bug report: v
OrmionModel
jsou špatně parametry u metodysetLimit
(přebýváoffset
). - Feature request, dotaz: nebylo by lepší ukládat řazení a stránku do fragmentu? Uřivatelsky mi přijde lepší, když jsem se někam dolistoval, dám F5, ale nehodí mě to za defaultní pohled.
Jestli to budu hodně potřebovat, tak to možná někdy v budoucnu udělám. Proto by mě ještě zajímalo – neplánuje se toto řešit nějak centrálně v Nette (uložení/načtení parametrů ve fragmentu)?
- Honza Marek
- Člen | 1664
v6ak napsal(a):
Jinak BC breaky – nedávno byl jeden BC break v IModelu, ale nevím, jaké jsou další plány Honzy. Já navrhoval změnu identifikace tlačítek (*"Dále jsem proti generování ID v podobě ++$this->toolbarButtonId. Takto někomu pod rukama přehodím pořadí tlačítek (třeba zveřejnit vs. smazat) a je v háji.
Určitě souhlasím s tím, že by tlačítka měla mít nějaké ID (ne jen číslo jako teď).
Dálě chci celkově předělat přidání sloupců a tlačítek. Zvažuju něco takového:
$column = $grid->addColumn("date", array(
"sortable" => true,
"text" => "Datum",
...
));
$column->setOption("dateTimeFormat", "j.n.Y");
To je samozřejmě BC break jako prase, ale je potřeba v tom udělat pořádek i s ohledem na to alternativní nastavování v šablonách.
Další moje plány jsou k vidění v issues na githubu – https://github.com/…idito/issues#list
- v6ak
- Člen | 206
Někdy je lepší udělat BC break, než vláčet historii. Na druhou stranu, v takovém případě je lepší toho udělat více naráz.
Přiznám se, že:
- Ten přistup s array se mi nelíbí, snadno se zde dělá chyba a IDE nenapovídá.
- Byl bych pro více typů sloupců, zpracováni DateTime možná do obecného sloupce nepatří.
- Honza Marek
- Člen | 1664
v6ak napsal(a):
- Ten přistup s array se mi nelíbí, snadno se zde dělá chyba a IDE nenapovídá.
To by se dalo vylepšit definováním konstant Column::NAME, Column::SORTABLE atd. Jinak to, že se ti to nelíbí znamená, že preferuješ klasické settery nebo se ti nelíbí ani jeden z těchto způsobů? .)
- Honza Marek
- Člen | 1664
Na stránku http://griddemo.janmarek.net/document_root/ jsem hodil nové ukázky. Nicméně v tuto chvíli je datagrid kompatibilní pouze s Nette 2.0 dev, což obnáší i nefunkční ajax (kromě jQuery UI oken).
- colek
- Člen | 59
Ahoj, chtěl bych se zeptat na asi elementární věc. Gridito mi funguje krásně, ale jen na homepage. Pokud se dostanu hlouběji ve struktuře webu, kde je zobrazení vázáno na nějaké id, toto id se nepředává ve vygenerovaných odkazech.
Pokud navštívím url: text/123, funguje vše v pořádku, id 123 se správně předá a vše se vykreslí.
$router[] = new Route('text/<id>', array(
'module' => 'Front',
'presenter' => 'Text',
'action' => 'showText',
'id' => NULL,
));
...
$id = $this->getParam('id');
$grid->setModel(new Gridito\DibiFluentModel($model->getTextById($id) ));
ale všechny vygenerované odkazy (stránkování, řazení) tvoří url text/?grid-sort…
můžete mi s tím nějak pomoci, díky.. :)
- Honza Marek
- Člen | 1664
Určitě by pomohl dát id jako persistentní parametr, ale to samozřejmě může dělat nějaký další bordel.
- TeeBee87
- Člen | 14
Lze nějak jednodušeji přidat sloupec, který je z joinuté tabulky?
<?php
$qb->select(array('t', 'o'))
->from('Helpdesk\Entities\Ticket', 't')
->leftJoin('t.owner', 'o')
;
?>
Potřeboval bych vypsat například sloupec o.login.
Momentálně to dělám takto:
<?php
$grid->addColumn("login", "Vlastník", array(
'renderer' => function($row) {
echo $row->owner->login;
}
));
?>
- Honza Marek
- Člen | 1664
$grid->addButton('name', 'Popisek')->setConfirmationQuestion('jo?');
// nebo
$grid->addButton('name', 'Popisek')->setConfirmationQuestion(function ($entity) {
return "Zničit $entity->name?";
});
Pak to vyhodí klasickej JS confirm.