[addon datagrid] DataGrid
- Honza Kuchař
- Člen | 1662
Ahoj, makám na komponentě TabControl (něco jako jQuery UI Tabs, ale
funkční i bez JS; hned jak to bude použitelný, tak to tady někam dám) a
narazil jsem na jeden takový problémek s formulářem na filtrování
v dataGridu. Když zaregistruji 2 instance datagridu pod stejným názvem, ale
v jiné úrovni komponent, tak mi potom nefunguje datepickter. Přišel jsem na
to, že se vygenerují stejné id
u inputů v obou datagridech.
Oprava je krásně jednoduchá :)
datagrid.php:846
FormControl::$idMask = 'frm-datagrid-' . String::capitalize($this->getName()) . '-%s-%s';
stačí změnit na:
FormControl::$idMask = 'frm-datagrid-' . String::capitalize($this->getUniqueId()) . '-%s-%s';
Potom mám ještě jeden dotaz, netýkající se přímo datagridu.
Vytvářím obecnou komponentu do které se jako „náplň“ dávají další
komponenty. Narazil jsem když u dataGridu přidávám akci
$grid->addAction("Edituj", "upravit!")
vygeneruje se mi link na
handler do té obslužné komponenty. Já jsem to vyřešil přepsání metody
link(). Je nějaké elegantnější řešení? Já to u svých komponent
řeším tak, že mají proměnou handlerComponent
(výchozí je
rodič) a přes ni generuji odkazy. Ale přepsání metody link()
nevyžaduje podporu komponenty, takže je asi vhodnější.
//EDIT: Nebo mám založit nové téma?
Editoval honzakuchar (3. 8. 2009 12:02)
- romansklenar
- Člen | 655
timbulko: r45
marek.dusek: r46
honzakuchar: bude opraveno v r47
Editoval romansklenar (3. 8. 2009 20:13)
- kozel
- Člen | 14
Jak ma tedy vypadat volani callbacku v presenteru a deklarace callbacku? (citovany kod jsem nepochopil)
romansklenar napsal(a):
$grid['name']->formatCallback[] = function($value, DibiRow $data) { ... };
Mam to tedy volat takhle? Jestli jo, tak mi to nefunguje (pouzivam nette-datagrid-beta.zip):
protected function createComponent($name) {
switch ($name) {
case 'seznamMajitelu':
$grid = new DataGrid;
$model = new Model;
$grid->bindDataTable($model->seznam());
$grid->addColumn('jmeno', 'Jméno');
$grid->addColumn('odkaz', 'Odkaz')->formatCallback[] = 'vytvorOdkaz';
$this->addComponent($grid, $name);
return;
}
}
function vytvorOdkaz($value, DibiRow $data) {
return Html::el('a')->href(HTTP_DIR . $data['id'])->setText($value);
}
- jarks
- Člen | 94
Polopatě: např. v definici gridu na políčko jmeno
zavěsíme:
$grid['jmeno']->formatCallback[] = array($this, 'jakSeJmenujeCallback');
k tomu je třeba o kousek dál vytvořit metodu, které předáme hodnotu políčka a celý řádek z databáze:
function jakSeJmenujeCallback ($value, DibiRow $data) {
// jestli je ve výsledku dotazu ve sloupci `aktivni` hodnota 1 (true), připiš to ke jménu:
if($data->aktivni == 1) return $value.' aktivní!';
else return $value;
}
- kozel
- Člen | 14
Predpokladam, ze o predani
DibiRow $data
se stejne jako o predani
$value
nemusim vubec starat, tyto hodnoty datagrid predava callbacku automaticky, ze? Bude to starou verzi DataGridu (ktera je mimochodem k dnesnimu dni stale ke stahnuti na https://componette.org/search/?…) – pouzivam
@version $Id: DataGrid.php 18 2009-05-20 22:41:25Z mail@romansklenar.cz $
Diky za reakce.
- jarks
- Člen | 94
Teď se dívám, že mám revizi 42 a zatím s ní nemám žádné problémy. stahovat můžete ze SVN.
- romansklenar
- Člen | 655
Prosím všechny:
Verze, která je v dokumentaci na stažení má zdokumentovány všechny featury tam. Pokud tam jakákoliv funkčnost co hledáte není popsána a není ani v ukázkové aplikace, tak v té verzi prostě není.
Věci v tomto vlákně se týkají většinou dalšího vývoje komponenty a dalších/nových featurek. Proto nekopírujte bezhlavě vše co se tu objeví.
Zrovna to co řešíte je ani ne tři týdny stará věc, která se mimochodem řešila o stránku zpátky, takže s betou to opravdu fungovat nebude.
- stromc3k
- Člen | 7
jak se da udelat ta administrace co je zde na obrazku? https://forum.nette.org/…rid-datagrid?…
Je na to v jquery plugin?
- dotTwelve
- Člen | 167
Co delam spatne?
Notice: Indirect modification of overloaded property Html::$class has no effect in /app/components/DataGrid/DataGridRenderer.php on line 153
Notice: Indirect modification of overloaded property Html::$class has no effect in /app/components/DataGrid/DataGridRenderer.php on line 216
- dotTwelve
- Člen | 167
Diky, uz to funguje.
Dalsi dotaz, jak prepisu ve sloupci Cena, kde nacitam pouze integer ve formatu DECIMAL z DB na cislo a za nej text ,– Kč
Potom bych potreboval zjistit nejak jednoduse ID bez toho abych nacital sloupec, pokud to je mozne a toto ID vlozil do odkazu ve sloupci Nazev, kde se nacita text, neco jako H1, ale potrebuji tento text odkazovat na ID presenteru.
Mam jeste dotaz k funkcnosti, jednou mi datagrid nabehne, pak zase ne, nekdy se zobrazi ale vycerpan casovy limit 60s, fakt nechapu.
Dik
Editoval dotTwelve (14. 8. 2009 17:24)
- timbulko
- Člen | 85
Dá sa v datagride po prevedení nejakej akcie (napríklad po zmene usporiadania alebo prejdení na ďalšiu stránku) vložiť do payloadu nejaké ďalšie dáta? Potreboval by som totiž po prevedení každej akcie v datagride vykonať jeden krátky js kód a na toto využívam práve payload + eval. Díky.
- romansklenar
- Člen | 655
timbulko: řešení mě napadá víc, třeba si přes API
DataGridu přes metodu isSignalReceiver
ověřit, jestli byl
přijat nějaký signál a podle toho zareagovat v rodičovské
komponentě.
Další možnost je podědit a modifikovat si metodu
signalReceived
aby volala nějakou událost, na kterou navěsíš
svůj callback, kterým data do payloadu presenteru předáš.
dotTwelve: už se to tu řešilo o stránku nebo dvě zpátky… stačí trošku hledat. K výkonu aplikace – nejdříve si aplikaci vyprofiluj třeba pomocí xDebugu a uvidíš kde má slabé místo, pokud se ukáže, že je to v DataGridu, tak pak se tím budu zabývat.
- Honza Kuchař
- Člen | 1662
Ahoj, malinký feture requestik. :) Když u TextColum předám jako maxLength nulu. Mohlo by se vypnout to ořezávání obsahu? Psát tam něco ve stylu: 99999999999 je pěkná prasárna. (TextColumn.php:25) Díky
Upraveno:
/**
* Formats cell's content.
* @param mixed
* @param DibiRow|array
* @return string
*/
public function formatContent($value, $data = NULL)
{
$value = htmlSpecialChars($value);
if (is_array($this->replacement) && !empty($this->replacement)) {
if (in_array($value, array_keys($this->replacement))) {
$value = $this->replacement[$value];
}
}
// translate & truncate
if ($value instanceof Html) {
$text = $this->dataGrid->translate($value->getText());
if($this->maxLength !== 0) {
$text = String::truncate($text, $this->maxLength);
}
$value->setText($text);
$value->title = $this->dataGrid->translate($value->title);
} else {
if($this->maxLength !== 0) {
$value = String::truncate($value, $this->maxLength);
}
}
foreach ($this->formatCallback as $callback) {
if (is_callable($callback)) {
$value = call_user_func($callback, $value, $data);
}
}
return $value;
}
- dotTwelve
- Člen | 167
Tak jsem stahnul posledni revizi datagridu, r50 a verzi Nette 0.8 stable a haze mi to chybu:
Class DataGrid contains 4 abstract methods and must therefore be declared abstract or implement the remaining methods (ArrayAccess::offsetExists, ArrayAccess::offsetGet, ArrayAccess::offsetSet, ...)
uz mi z toho asi jeb*e! help!
Muze byt problem ve verzi PHP 5.2?
Editoval dotTwelve (14. 8. 2009 21:01)
- romansklenar
- Člen | 655
dotTwelve:
- vývojová verze Nette (0.9) ⇒ vývojová verze DataGridu
- stabilní verze Nette (0.8) ⇒ stabilní verze DataGridu (beta)
Pohled do dokumentace nebo do kódu (i z popisu té chyby to jde pochopit) by úplně stačil…
honzakuchar: jojo přídám
Editoval romansklenar (15. 8. 2009 8:17)
- Honza Kuchař
- Člen | 1662
Přidal jsem do poznámky o verzích, že vývojová verze Nette je 0.9. Jinak už mi opravdu nevím, jak výše zmíněnou informaci (už asi po 20té) objasnit.
honzakuchar: jojo přídám
Díky
Chtěl jsem se ještě poradit s takovou hezkou feature, kterou připravuji. V současném datagridu dělám buňky editovatelné. (přímo v té tabulce) A jde mi o následující: Mám si datagrid podědit a nějak poupravovat (asi dost špinavě) a potom přidat do extras nebo se to pokusit upravit přímo v datagridu, že by jsi to potom přidal jako feature? Musí se ale nějak vymyslet implementace. Nejhezčí by asi bylo něco ve stylu:
$grid->addColumn("abc","cbd")->editable = true; // U položek co mají jasnou hodnotu ze se znamu by se musel udělat další column - asi SelectBoxColumn a v ní by už byly i možné hodnoty?
Aktuálně to řeším následovně:
- Předání id řádku (současně to řeším v id tr ve formátu:
$grid->getUniqueId()."___".$rowId
) - Předání názvu políčka (před generování JavaScriptu jsem si
z datagridu tyhle informace vytáhl a zakódoval pomocí
json_encode()
, tyhle data si předám pouze jednou pro celý datagrid a potom se informaze v toho pole vytáhnou pomocí pořadí sloupečků, přidávání id ke každému políčku by bylo datově dost náročné) - Editace textového políčka je velice jednoduchá. U políček, které
mají jasnou hodnotu se musí zobrazovat selectbox. (možné hodnoty se musí od
někud vzít, tzn. asi bych vytvořil nějakou proměnnou v tom
SelectBoxColumn, kde by se uložily možné hodnoty, tzn.
->selectboxFilter()
by si mohl vyzít data právě z této proměnné) (např.: stav zakázky) U políček s datem se zobrazuje datepicker.
Jak se tak na to dívám, možná vy stálo za zvážení, jestli na tuhle věc neudělat zvláštní komponentu (tzn. necpat to přímo do datagridu), která by tu editaci propojila jak s datagridem, tak s plným editačním formulářem. (z formuláře by si vytáhla ty možné hodnoty – protože tohle bych v tom formuláři stejně muselo ošetřit + podmínky navěšené na tom políčku a do datagridu by pomocí jQuery povykreslovala upravitelné textové políčka + selectboxy + datepickery a podobné srandy) Co vy na to?
Výhody a nevýhody
- data z té jedné buňky se ukládají hned po tom co buňku opustím (pokud se změní obsah) (můžete si to upravit tak, že se objeví třeba nějaké tlačítko nebo tak něco – upravil jsem ty editační políčka tak, že podporují události focus, blur a change, takže na to můžete navěsit opravdu co vás napadne)
- Musím mít další obshužný handler – přijdou mi data pouze z jednoho políčka (prostě to musím zpracovat extra), ale nic složitého – 1 jednoduchý SQL dotaz.
- Zatím není nijak ošetřeno co se stane když vlezou 2 do stejné buňky. (ale mám nápad na relativně čisté řešení :) )
- romansklenar
- Člen | 655
Spíš bych to viděl na zvlášť poděděnou komponentu. Pokud toto chceš udělat dobře a čistě tak už to není nic jednoduchého. Já už do datagridu nic cpát nechci, protože už tam mám vše co jsem potřeboval i všechy feature requesty, které se mi v základu líbily. Pokud se má zachovat rychlost, tak už se nic přidávat nebude. Sám když potřebuju v projektech něco navíc tak si ho podědím a dopíšu. Proto i napovídání a asi i přesouvání řádků pomocí jQuery i toto co píšeš nechám na každém z vás. Maximálně dodělám ještě časem skrývání sloupců a až vyjde Nette 0.9 vyjde i DataGrid.
Můžete do extras klidně přidávat SortableDataGrid i EditableDataGrid a podobné.
- Honza Kuchař
- Člen | 1662
Díky za odpověd. Bude to tak i přehlednější. ;) Nakreslil jsem si na to takové schéma a ve spojení s tím AppFormem (pokud tedy půjde vše podle plánů) by to nemuselo az zas tak slozite. Jen pro info, tento plug-in zpomaluje pouze u klienta (jQuery), na straně serveru se akorát pošlou informace o sloupečcích.
- Honza Kuchař
- Člen | 1662
Ahoj, ještě mám jeden dotaz. Když používám jako formát data
%x
občas se mi datum zobrazí jako 08/12/09 a občas jako
12.8.2009. (většinou když 2× po sobě zmáčknu F5) Netušíš, kde by mohla
být chyba? Locale je nastaveno na ČR. Předpokládám, že chyba nebude
v datagridu, ale i tak nevíte někdo čím to je? Divné je, že se to
zobrazí občas tak a občas tak. :( Vypozoroval jsem, že se je jedno jestli to
běží v AJAXu nebo standardně.
- Honza Kuchař
- Člen | 1662
Ok, takže chybu hledat v PHP. O opravdu dělá to VŽDY když jdou 2 požadyvky tesně za sebou. Resp. zpracovávají se zároveň. PHP o tom cosi píše:
Warning
The locale information is maintained per process, not per thread. If you are running PHP on a multithreaded server API like IIS or Apache on Windows, you may experience sudden changes in locale settings while a script is running, though the script itself never called setlocale(). This happens due to other scripts running in different threads of the same process at the same time, changing the process-wide locale using setlocale().
- ji_ri_k
- Člen | 44
Ahoj, ve své aplikaci zkouším použít tvůj datagrid. Za prvé velká
pochvala, super práce. Ale narazil jsem na malý problém při přídávání
action.
Příklad:
$grid->addActionColumn('Action')->getHeaderPrototype()->style('width: 20%');
funguje OK
ale
$grid->addActionColumn('Možnosti')->getHeaderPrototype()->style('width: 20%');
již vyhodí vyjímku:
InvalidArgumentException
Component name must be non-empty alphanumeric string, ‚Možnosti‘ given.
Zatím jsem neměl chvíli prostudovat jakým způsobem se kontroluje ten název sloupce, ale pravděpodobně to nesbaští české znaky
- dotTwelve
- Člen | 167
jarks napsal(a):
Polopatě: např. v definici gridu na políčko
jmeno
zavěsíme:$grid['jmeno']->formatCallback[] = array($this, 'jakSeJmenujeCallback');
k tomu je třeba o kousek dál vytvořit metodu, které předáme hodnotu políčka a celý řádek z databáze:
function jakSeJmenujeCallback ($value, DibiRow $data) { // jestli je ve výsledku dotazu ve sloupci `aktivni` hodnota 1 (true), připiš to ke jménu: if($data->aktivni == 1) return $value.' aktivní!'; else return $value; }
Muze mi nekdo rict, proc mi to hazi chybu:
Argument 2 passed to jakSeJmenujeCallback() must be an instance of DibiRow, none given
- Honza Kuchař
- Člen | 1662
dotTwelve: DibiRow se předává až v jedné z novějších revizí. Co máš za revizi?
- ji_ri_k
- Člen | 44
honzakuchar napsal(a):
ji_ri_k → Za ty české znaky pokud vím nemůže datagrid ale přímo Nette.
Všiml jsem si té části která tu vyjímku vyvolala. Právě jsem psal,
že jsem to moc neprohlížel.
Ale vím, že v datagridu původním (tuším ten pro nette 0.8) a nette ve
verzi 0.9 revize 392 mi to běhalo v pohodě.
- mkoubik
- Člen | 728
Když jsem kdysi viděl data grid jako příklad v dokumentaci k Nette, rozhodl jsem se si jako cvičení napsat vlastní (a lepší) data grid, který jsem pak začal i používat.
S vývojem Nette ale začal můj dg funkčně zaostávat za tím oficiálním, takže teď přemýšlím o přechodu na něj, ale přijde mi, že je primárně určený pro data z databáze. Všude samé DibiRow apod.
Dá se data grid používat i obecně? Nejlepší přístup by byl předhodit mu místo modelu objekt třídy implementující nějaké rozhraní a nechat data grid, aby si z něj tahal data a předával mu informace o řazení, stránkování, filtrování atd. Existuje něco takového?
- romansklenar
- Člen | 655
Tento DataGrid není žádný „oficiální“, je jen v extras jediný zveřejněný. Je určen pro data z databáze ale opravdu by neměl být problém si podědit potřebné věci a přepsat si je. Já do DataGridu necpu kdejakou věc, která někoho napadne nebo by to tam rád měl, protože na to už nemám čas ani motivaci.
Nejlepší přístup by byl předhodit mu místo modelu objekt třídy implementující nějaké rozhraní a nechat data grid, aby si z něj tahal data a předával mu informace o řazení, stránkování, filtrování atd. Existuje něco takového?
Tak to i funguje, nepředhazuje se mu model ale objekt třídy
DibiDataSource
, ten si všechno zařizuje přes své API.
DibiRow
zase nemusí být jen řádek z databáze, ale i obecná
data jednoho řádku.
Editoval romansklenar (17. 8. 2009 8:45)
- Honza Kuchař
- Člen | 1662
dotTwelve napsal(a):
honzakuchar napsal(a):
dotTwelve: DibiRow se předává až v jedné z novějších revizí. Co máš za revizi?
Mam stazenou verzi beta, ktera bezi bez problemu na Nette 0.8
Jakou verzi Datagridu mam tedy stahnout, aby vse bezelo tak jako ted?
Betě to na 100% není. Takže pokud to chceš používat, tak musíš použít vývojovou verzi ze SVN a Nette (0.9)
- Honza Kuchař
- Člen | 1662
No dobra ale má to 2 háčky:
- Neposkytuji technickou podporu (až to někdy dám do extras tak až potom)
- Kód není nic moc protože je to ve velice rané fázi vývoje.
- Funguje to jenom na nejnovější verzi prohlížečů. (ty políčka nejsou inputy)
- Na aktuálnější verzi se podívej zde.
- Tzn. je vyřešená validace a filtrování inputů (je sdílená s editačním formulářem – tzn. je nastavená pouze jednou! :) )
- Funguje to tak, že vytvoříš gatagrid a vytvoříš editační formulář a řekneš mu co má odkud brát. Ono už si to samo vybere jestli to bude selecbox (z toho edit formuláře) nebo něco jiného.
Takže pokud to chceš používat tak můžeš, ale jako tester. ;) Když tak mi napiš na e-mail.
- Honza Kuchař
- Člen | 1662
Ještě jedna věc: je v plánu udělat ovládní šipkama.
A ještě jedna feature, že nad stanovený počet řádků v DG nejsou buňky
editovatelné hned, ale až po kliknutí.
Použití je přibližně následující:
$grid = new EditableDatagrid($tab,$name);
$grid->bindDataTable(Zakazky::getDataSource("zakazky"));
$grid->keyName = "IdZakazky"; // Primární klíč - pro identicifaci
// Normálně nastavuji jako v normálním datagridu a někde na konci až už je celý datagrid nastaven tak udělám:
$grid->setEditForm($this["tabs"]["edit"]->content);
$grid->addEditableField("Nazev");
$grid->addEditableField("Popis");
$grid->addEditableField("IdStavuZakazky");
// Toť vše nyní jsou políčka Nazev, Popis a IdStavuZakazky editovatelne. Z formuláře se třeba načte, že se u IdStavuZakazky bude zobrazovat selectbox a použije se jako překladový slovník...
V šabloně se to potom vykresluje pomocí:
{control datagrid:editable}
Nebo tak nějak přibližně :)
//EDIT: v datagridu NENÍ bug! :)
Editoval honzakuchar (19. 8. 2009 10:32)
- romansklenar
- Člen | 655
honzakuchar napsal(a):
Použití je přibližně následující:
$grid->rememberState = false; // Pamatuje si i bez tohoto - v dataGridu je bug
Nic takového u sebe nepozoruju, jsi si tím jistý?
- Honza Kuchař
- Člen | 1662
romansklenar napsal(a):
honzakuchar napsal(a):
Použití je přibližně následující:
$grid->rememberState = false; // Pamatuje si i bez tohoto - v dataGridu je bug
Nic takového u sebe nepozoruju, jsi si tím jistý?
Jo měl jsem to ohlásit. Nic závažného. Když máš na stránce 2 datagridy, tak se to řazení, třídění a tak podobně různě přehazuje mezi těma dvěma datagridy. Jestli chceš pošlu příklad.
//EDIT: to co jsem to tam přidal už je taky nějaká chvíle, takže je klidně možné, že už je to opravené.
//EDIT 2: Už je to opravené. ;) Omlouvám se za zmatek.
Editoval honzakuchar (18. 8. 2009 23:06)
- romansklenar
- Člen | 655
Chyba bude někde mezi klávesnicí a židlí – nezapomněl jsi například aktualizovat i css, js a obrázky při aktualizaci datagridu?
- Honza Kuchař
- Člen | 1662
dotTwelve → stáhni si celý datagrid ze SVN a uvidíš, že to bude fungovat. ;)
- dotTwelve
- Člen | 167
honzakuchar napsal(a):
dotTwelve → stáhni si celý datagrid ze SVN a uvidíš, že to bude fungovat. ;)
Funguje to, zobrazily se šipky nahoru i dolu pod sebou, to je spravne,
ovsem nefunguje razeni. Kliknu na sipku, roztoci se spinner ale sloupec si
neseradi.
Muze byt chyba v zapisu datagridu v sablone? Pouzivam posledni verzi nette
0.9 a zapis je takovy to, podle verze 0.8
@{?$nabidkaPozemku->render()}
- PetrP
- Člen | 587
dotTwelve napsal(a):
Funguje to, zobrazily se šipky nahoru i dolu pod sebou, to je spravne, ovsem nefunguje razeni. Kliknu na sipku, roztoci se spinner ale sloupec si neseradi.
Muze byt chyba v zapisu datagridu v sablone? Pouzivam posledni verzi nette 0.9 a zapis je takovy to, podle verze 0.8@{?$nabidkaPozemku->render()}
A nemáš tam něco jako
{if ...}
@{?$nabidkaPozemku->render()}
{/if}
Protože je potřeba ozavináčovat všechno „na cestě“ ;]