NiftyGrid – Datagrid pro Nette 2 s velkou škálou funkcí
- Nifty
- Člen | 45
llook
- Editační tlačítko nic dělat nemá. Je to příklad odkazu na jiný Presenter bez AJAXu, viz dokumentace, a kdybych tam nechal odkaz, tak by to hodilo neexistující stránku.
- Opraveno, byla tam špatně nastavená třída, díky.
- DoKa
- Člen | 3
Zdravím,
chtěl bych se zeptat, jestli se dá doplněk upravit pro zdroj dat
z dibiDataSource popř. co mám udělat, aby mi fungoval.
Zkoušel jsem tohle, ale nějak nefunguje:
$conn = dibi::getConnection();
$source = new \NiftyGrid\NDataSource($conn->dataSource('SELECT * FROM [articles]'));
$this->setDataSource($source);
Předem díky za odpověď.
- Nifty
- Člen | 45
Ahoj, Dibi zatím neni podporováno.
NDataSource slouží pouze pro Nette\Database a NotORM, viz dokumentace.
Do budoucna to plánuju, ale až bude víc času :)
- David Matějka
- Moderator | 6445
moc pěkný :) jen jsem si všim jedný chybky – při zapnuté řádkové editace nefunguje uložení pokud kliknu na enter. a možná by nebylo špatný tu editaci vyřešit stylem adminer – do editace se dostat dvojklikem a moci editovat víc řádků a jen jednou odeslat..
- Nifty
- Člen | 45
echo
O víkendu to zpracuju a updatnu na Githubu.
matej21
Ten dvojklik je dobrý nápad. S tím enterem je to složitější. Přes
javascript by to šlo udělat, ale snažil jsem se to udělat funkční i bez
(mimo autocomplete a datepicker). Jde o to, že celý grid je dělán jako
jeden formulář, který je rozdělený na containery. Pokud se klikne
v editaci na enter, tak se to odešle přes první submit (a to je submit na
filtrování) a tím pádem to nepůjde. Promyslím to ;)
- MaKo
- Člen | 4
Musím se také připojit ke gratulaci. Výborná práce.
Chtěl jsem použít komponentu v projektu, který z historických a administrativních důvodů musí běžet na PHP 5.2, takže jsem musel upravit kód, nicméne komponenta skvěle funguje.
Měl bych dotaz?
Je možné nějak přednastavit filtr? Chtěl bych otevřít grid s již
přednastaveným filtrem na jeden sloupec, aby se rovnou aplikoval.
- MaKo
- Člen | 4
Tak zatím jsem si poradil takto:
Mam ve tříde presenteru MaintainancePresenter
factory metodu
createComponentLogGrid()
, která vytváří instanci
LogGrid
(extends Grid
), ve které je definován
sloupec „Batch“, dle kterého chci vyfiltrovat při zobrazení data.
Část kódu Latte šablony, ze které se otevírá view s gridem:
{var $args = ["logGrid-filter[Batch]" => $batchNumber]}
<a n:href="Maintenance:log (expand) $args">Show detailed log from updating process.</a>
Nette vygeneruje link (příklad):
http://mydeveldomain.dev/projects/?logGrid-filter%5BBatch%5D=import-1339580983&action=log&presenter=Maintenance
Po kliknutí zobrazí grid se správně nastaveným filtrem.
Mám tak v šabloně napevno název sloupce, ale to už přežiju :)
Editoval MaKo (13. 6. 2012 12:10)
- echo
- Člen | 134
MaKo napsal(a):
Měl bych dotaz?
Je možné nějak přednastavit filtr? Chtěl bych otevřít grid s již přednastaveným filtrem na jeden sloupec, aby se rovnou aplikoval.
Zdravím. Pokud to dobře chápu, tak filtr by se měl zaregistrovat už při vytváření sloupce metodami setTextFilter() setNumericFilter() … viz. třída Column.
pozn.: Do url by se lozit vůbec němělo.
- MaKo
- Člen | 4
echo napsal(a):
MaKo napsal(a):
Měl bych dotaz?
Je možné nějak přednastavit filtr? Chtěl bych otevřít grid s již přednastaveným filtrem na jeden sloupec, aby se rovnou aplikoval.Zdravím. Pokud to dobře chápu, tak filtr by se měl zaregistrovat už při vytváření sloupce metodami setTextFilter() setNumericFilter() … viz. třída Column.
pozn.: Do url by se lozit vůbec němělo.
Možná jsem to nenaformuloval správně. Šlo mi o to přednastavit takto
nadefinovanému filtru (pomocí metod
setTextFilter() setNumericFilter() ...
) atd nějaké „default“
hodnoty.
Editoval MaKo (13. 6. 2012 14:33)
- Nifty
- Člen | 45
MaKo
Nestačilo by do DataSource přidat podmínku?
$source = $database->select('...')->where('...');
Edit: Nebo by ještě mohlo jít přímo přidat hodnoty do filtru v configure.
$this->filter[$column] = $value;
Za předpokladu, že daný sloupec $column má zadeklarovaný filtr.
Editoval Nifty (13. 6. 2012 14:49)
- MaKo
- Člen | 4
Nifty napsal(a):
MaKo
Nestačilo by do DataSource přidat podmínku?$source = $database->select('...')->where('...');
Edit: Nebo by ještě mohlo jít přímo přidat hodnoty do filtru v configure.
$this->filter[$column] = $value;
Za předpokladu, že daný sloupec $column má zadeklarovaný filtr.
Díky za rady. Nevšiml jsem si že je filter public. Zkoušel jsem nastavit filtr po vytvoření gridu v presenteru:
public function renderBatchLog($batch_number)
{
$this['logGrid']->filter['Batch'] = $batch_number;
$this->setView('log');
}
ale to už je pozdě.
První variantu s DataSource jsem nezkoušel, protože mi nejde o permanentní nastavení filtru, ale pouze pro iniciální (první zobrazení). Pak ať si uživatel filtr zruší a nastavuje si ho jak chce.
Pak jsem zkusil druhou variantu – nastavit přes configure (poslat data přes předávaný presenter)
if (isset($presenter->batch_number))
$this->filter['Batch'] = $presenter->batch_number;
ale pak mi zůstala hodnota nastavená pořád.
Editoval MaKo (13. 6. 2012 15:43)
- Nifty
- Člen | 45
Tak to bude složitější. Dalo by se kontrolovat, zda je konkrétní filtr prázdný a podle toho tam nastavit defaultní hodnotu. Tím by fungovala změna daného filtru, ale při zrušení celého filtru by se tam znovu nastavila defaultní hodnota. Zatím mě nenapadá žádné pořádné řešení. Možná by šlo vymyslet něco přes session, ale to bych do Gridu motat nechtěl.
- echo
- Člen | 134
Přihazuji DataSource pro Doctrine2: https://github.com/…taSource.php
Používá to QueryBuilder, který se předá jako 1 parametr v constructoru(). Druhým parametrem je primární id.
Příklad:
- QueryBuilder:
$entityManager->createQueryBuilder('perm')
->select('p')
->from('Packages\Pages\Entities\Page', 'p');
- Source
$source = new \NiftyGrid\DoctrineDataSource($this->qb, 'p_id');
p_id se přeloží na p.id
- Přidání sloupce
$this->addColumn('p_title', 'Titulek')
->setTextFilter()
->setTextEditable();
p_title se opět přeloží na p.title
Zatím je to ve fázi raného testování.
- wer
- Člen | 3
Tak tento datagrid se mi vyloženě zamlouvá. :-)
Ale pár připomínek bych měl:
- Nefunguje filtr pro nulu. Nula ve filtru se chová jako prázdný filtr. A to jak u textových polí, numerických polí i u booleanů. Hlavně u booleanů to dost bolí. Problém se projevuje i v ukázkovém příkladu, kde nefunguje filtr na nulu ani ve sloupci Titulek ani ve sloupci Zobrazení.
- Hromadné akce nad jednotlivými řádky jsou krásné, ale přece jen by se spíše hodilo něco jako addToolbarButton pro obecné akce nad celým gridem (např. „přidat položku“ nebo „exportovat“).
- Nelíbí se mi, že se k formátování přes CellRenderer používá style místo class. CSS se tak nedá oddělit od kódu. (To je ovšem jen problém standardní šablony.)
- A jen tak k zamyšlení, nešlo by místo subgridu mít obecnou subkomponentu?
Editoval wer (4. 7. 2012 13:52)
- xkendy
- Člen | 3
Grid super, diky za nej a tvoji praci.
Mel bych dotazek k nastaveni filteru pro danou polozku. Pokud pouziji
$this->addColumn('name', 'Jmeno', '10%', 15)->setTextFilter();
tak pokud moje tabulka neobsahuje sloupec s nazvem „id“, tak nette havaruje s error 500, kterou vypise do mista, kde maji byt ovladaci prvky (buttony), zbytek gridu se vykresli.
V error logu je pak toto:
[2012-07-10 21-50-41] PDOException: No reference found for $tabulka->id. in libs/Nette/Database/Reflection/DiscoveredReflection.php:140
Zkousel sem pouzit i parametr:
$this->addColumn('name', 'Jmeno', '10%', 15)->setTextFilter("name");
ale bez zmeny.
Kdyz alterem rozsirim tabulku o sloupec ID, chyba zmizi.
Lze toto konfiguracne obejit, nebo to musis fixnout v kodu ?
Verzi gridu mam stazenou ze sajtu nette.
Editoval xkendy (10. 7. 2012 22:19)
- Nifty
- Člen | 45
Jsem rád, že je o grid zájem, ale v současné době je práce moc a času málo :(
wer
Díky za report, nevim jak jsem to s tou nulou mohl přehlídnout :)
xkendy
Ano, skutečně je tam natvrdo jako primární klíč „id“. Otázka je,
jestli primární klíč umí zjistit i jiné databázové vrstvy, než N\D.
Když o tom teď s odstupem přemýšlím, tak by se primární klíč měl
získávat výhradně z DataSource, i kdyby to mělo vracet jen
to „id“.
blacksun
Super, až se na to budeš chystat, doporučuju přečíst https://github.com/…rid/issues/1
Ve zkratce jde o to, že se přestane používat podmínka HAVING v SQL a
zmizí metoda getSelectedRowsCount v DataSource kvůli rychlosti gridu.
Editoval Nifty (16. 7. 2012 10:37)
- Kryšpin
- Člen | 27
Jak si teď hrauji s Niftygrid, tak jsem si pro svoje potřeby přidal componentu ButtonUpper a upravil třídu Grid a šablonu Grid a nyní lze přidávat tlačítka před tlačítko odkazující na stránku pomocí addButtonUpper. Používám to například pro tlačítko přidat položku.
Je to jednoduché, ale pokud bude zájem a bude to Nifty chtít zahrnout do další verze, mohu poskytnout.
Moje přípomonky: chtělo by to převést všechny atributy co jsou zastaralé do CSS (například cellpadding, cellspacing, width, border, align)
- Hafran
- Člen | 121
Dobrá práce,
přidám se taky k tomu, aby stylování bylo jednodušší a přehlednější.
Tedy vše přes css.
Jde nějak přidat třída rovnou celé tabulce? něco jako u formulářu: $this->getElementPrototype()->class(‚class‘);
edited: 18.7.2012
Pardon, jistěže jde – stačí to změnit v šabloně. Už jsem z Nette
hrozně zmlsanej. ;)
Editoval Hafran (18. 7. 2012 15:40)
- tajo
- Člen | 20
Pokročili jste nějak s Dibi ?
Zkoušel jsem si ten interface implementovat pomocí https://api.dibiphp.com/…aSource.html
a částečně mi to i funguje. Potíž mám ale třeba s in-row editací.
Konkrétně je problém s řádkem 818 v Grid.php:
$row = $rows[$this->activeRowForm];
NDataSource jde v pohodě
DibiDataSource se asi neumí fetchnout při přístupu přes [ ], pokud ho
fetchnu už v implementaci interface:
public function getData()
{
return $this->data->fetchAll();
}
tak to activeRowForm stejně odkazuje na nesmyslné řádky a vůbec to
neodpovídá reálu
(Věci jako Filtry jsem raději ještě vůbec rozběhnout nezkoušel)
- Milo
- Nette Core | 1283
Na gist jsem vystavil mojí
implementaci data source pro DibiFluent
. Nevím jestli bude
fungovat za všech okolností, obzvlášť při grupování.
- Nifty
- Člen | 45
Dneska jsem updatnul Grid na Githubu, hlavně opravy:
- Opraven filtr pro nulu.
- Primární klíč se nyní zjištujě přímo z DataSource (už to nemusí být pouze „id“). V interface je to jako povinná metoda.
- Nahrazeny některé zastaralé HTML atributy v šabloně.
- Upraveno filtrování dat.
- Již neni podporováno filtrování s podmínkou HAVING.
- Metoda getSelectedRowsCount odstraněna z DataSource.
- Sloupec už není potřeba označovat jako alias.
- Pokud je v Gridu potřeba sloupec z připojené tabulky a chceme v daném sloupci filtrovat záznamy, použije se metoda u sloupce setTableName(„table.column“).
- Tato úprava je především kvůli zrychlení Gridu, zejména při velkém množství záznamů. Více info viz github
$dataSource = new NDataSource($articles->select("article.title, user.username AS username"));
...
$this->addColumn("username", "Uživatel")
->setTableName("user.username")
->setTextFilter();
5)Už dříve přidána podpora pro dvojklikovou editaci a potvrzení enterem. [díky echo]
Všechny úpravy jsou zatím pouze na Githubu.
Hafran
Záznamy pro subgrid se vybírají až po rozkliknutí subgridu a pouze pro ten
konkrétní subgrid.
V případě těch článků se načtou pouze komentáře pro daný článek
podle klíče :)
- Milo
- Nette Core | 1283
Chtěl jsem to zkusit, protože na možnost názvu vlastního primary key jsem čekal, ale máš tam parse error.
EDIT:
A je tam toho víc.
Navíc sice jde nastavit název sloupce s primárním klíčem, ale v Grid.php
se natvrdo používá 'id'
a to na spoustě místech.
EDIT2:
A když už tu hlásím chyby, v šabloně
je taktéž chyba. ['{$primaryKey}']
Editoval Milo (25. 7. 2012 8:49)
- Nifty
- Člen | 45
Milo
Tak to je hodně divný, u sebe na localu jsem to měl v pořádku. Asi mi
nějak zablbnul klient pro github. Každopádně díky, už by to mělo být
opraveno.
EDIT: Ještě upravim ty primární klíče.
EDIT2: Primární klíč opraven v Gridu. Snad už to bude v pořádku :)
Editoval Nifty (25. 7. 2012 13:28)
- Nifty
- Člen | 45
- DibiFluentDataSource přidán do NiftyGridu (autor Milo)
- Aktualizovaná dokumentace (filtrování, podpora knihoven)
- Příklad ke stažení v dokumentaci aktualizován
- bumprask
- Člen | 59
Na jedné stránce mám tento grid co vypisuje záznamy a přímo pod ním formulář pro vkládání záznamů do tohoto gridu. Vložení záznamu probíhá ajaxem, po odeslání proběhne tedy klasicky invalidace všech snippetů. V případě, že mám ovšem navolené v gridu filtry dojde k zrušení těchto filtrů. Tedy nevím jak mám na jedné stránce vložit záznam a zároveň invalidovat snippet, aniž by se neresetovaly filtry. Prosím může někdo poradit jak by se toto dalo řešit?
invalidace v rámci komponenty funguje, ale invalidace gridu z jiné komponenty ne.
Editoval bumprask (26. 7. 2012 18:13)
- Nifty
- Člen | 45
Vkládání nových záznamů chystám. Asi to udělám tak, že to využije nastavené editovatelné sloupce, takže jediné co bude potřeba nastavit, bude callback pro uložení. Možná i ten callback by se mohl sjednotit. Ještě přemýšlím, kam pro to umístit tlačítko :) (možná buttonUpper od Kryšpina)
- bumprask
- Člen | 59
Nifty napsal(a):
Vkládání nových záznamů chystám. Asi to udělám tak, že to využije nastavené editovatelné sloupce, takže jediné co bude potřeba nastavit, bude callback pro uložení. Možná i ten callback by se mohl sjednotit. Ještě přemýšlím, kam pro to umístit tlačítko :) (možná buttonUpper od Kryšpina)
A prosím dalo by se naznačit, co pozměnit, aby se grid dal invalidovat i mimo komponentu tak, aby se filtry zachovaly?
- Nifty
- Člen | 45
Předpokládám, že bez ajaxu to funguje. Myslim, že nepotřebuješ invalidaci gridu z jiné komponenty, ale invalidaci komponenty z gridu. Problém je v tom, že když v gridu přes ajax provedeš nějakou akci (filtrování, ..), tak se mimo komponentu(grid) nezmění odkazy s perzistentními parametry z gridu. Tim pádem se kliknutím na odkaz mimo grid ztratí celý stav gridu. Nenapadá mě žádné jiné rozumné řešení, než to propojit s gridem (třeba jako komponenta v gridu). (neřikám ale, že řešení není, třeba mě někdo opraví)
- Kurtas
- Člen | 109
Ahoj,
lze nejak pres tento grid resit nasledujici situaci:
- potrebuji pouze pro urcite radky mit moznost zobrazit subGrid, lze to?
- Hodila by se moznost „Insert new row“, pises ze na tom pracujes tak parada
- Hodila by se i moznost misto subgridu vlozit form
PS: Na Githubu jsem do pull requstu pridal podporu translatoru + u Date poli (DateFilter a DateEtitable) jsem pridal parametr readonly, aby uzivatel nemohl vepsat hodnoty ale pouze vybrat pres DatePicker
Editoval Kurtas (31. 7. 2012 10:08)
- Nifty
- Člen | 45
ad 1) V současné verzi to nelze, ale šel by pro to udělat callback. Poznamenám si to :)
ad 3) Tohle mě napadlo při vytváření gridu taky, ale nakonec jsem to vypustil. Když o tom teď přemýšlím, tak pro nějakou rozšířenější editaci nebo přidávání záznamů 1:n by to nemuselo být špatné. Ještě to promyslím.
Ten translator vypadá v pořádku, ještě to vyzkoušim a mergnu, díky :)
U toho date pole je problém s filtrem, kde by nešli psát operátory (>, <>, ..). Já osobně ten datum kolikrát napíšu radši ručně, je to rychlejší. Ale v tom DateEditable si to využití najde. Mužeš to prosim pullnout ještě jednou bez toho filtru?
Editoval Nifty (31. 7. 2012 19:14)
- Kurtas
- Člen | 109
Ok pulnu, ale dle me to ma smysl i u filtr, kdyz chce vyvojar dovolit psat do Filteru tak staci nastavit readonly = false, resp defaultne je povoleno psat do filtru … btw ten bod 1 jsem vyresil prave pres ten callback mam to tam taky pullnout? Napsal jsem to jak pro subGrid tak pro Action Button.. + taky mam eng. template + prepsane texty do translator maker
Editoval Kurtas (31. 7. 2012 19:28)
- mochja
- Člen | 20
narazil jsem na problem, chci si vytvorit grid s uzivatelema bohuzel jakmile nastavim setTextEditable() pro name dostanu Nette\InvalidArgumentException: „Component with name ‚id‘ does not exist.“
errorlog: https://www.dropbox.com/…d13e640.html
<?php
namespace AdminModule;
use \NiftyGrid\Grid;
class UserGrid extends Grid
{
protected $users;
public function __construct($users)
{
parent::__construct();
$this->users = $users;
}
protected function configure($presenter)
{
$source = new \NiftyGrid\NDataSource($this->users->select('id, name'));
$this->setDataSource($source);
$this->setWidth("1000px");
$this->setDefaultOrder("users.id DESC");
$this->setPerPageValues(array(20, 50, 100));
$this->addColumn('name', 'Name', '210px', 30)
->setTextEditable()
->setTextFilter();
$self = $this;
$this->setRowFormCallback(function($values) use ($self, $presenter){
$vals = array(
//"login" => $values["login"],
"name" => $values["name"],
);
$presenter->context->database->table('users')->find($values["id"])->update($vals);
$self->flashMessage("Záznam byl úspěšně uložen.", "grid-successful");
}
);
$this->addButton(Grid::ROW_FORM, "Rychlá editace")
->setClass("fast-edit");
}
public function handleDelete($id)
{
$this->presenter->context->database->table('users')->find($id)->delete();
if(count($id) > 1){
$this->flashMessage("Vybraný uživatelé byly úspěšně smazány.","grid-successful");
}else{
$this->flashMessage("Uživatel byl úspěšně smazán.","grid-successful");
}
$this->redirect("this");
}
}
Pouzivam verzi z githubu.
tak problem byl nakonec v zaznamu, jestly mam zaznam s id 0, tak skoncim s exception
Editoval mochja (1. 8. 2012 1:32)
- Nifty
- Člen | 45
Měl jsem teď docela fofr, tak jsem to tu moc nesledoval.
Každopádně vkládání nových záznamů jsem dnes hodil na Github jako součást globálních tlačítek, které jsou taky novinkou.
Přidání nového záznamu je závislé na informacích o editaci u sloupce, takže není potřeba nic nastavovat, pouze přidat tlačítko.
$this->addGlobalButton(Grid::ADD_ROW, 'Přidat nový záznam');
Zpracování formuláře probíhá ve stejném callbacku jako editace.
$this->setRowFormCallback(function($values) use ($articles){
if(isset($values['id'])){
//update
}
else{
//insert
}
}
Vlastní použití globálního tlačítka
$this->addGlobalButton('trashed', 'Zobrazit články v koši')
->setLink($presenter->link('trashed'))
->setClass('trash')
->setAjax(FALSE);
Teď se budu snažit postupně vyřizovat pull requesty/issues. Mohl by si tu eng šablonu hodit třeba na gist/pastebin nebo poslat přes pm?
Editoval Nifty (11. 8. 2012 1:08)