ublaboo/datagrid: mocný, rychlý, rozšiřitelný, hezký, anglicky dokumentovaný datagrid

japijana
Člen | 11
+
0
-

@PavelJanda / keď je column hidden, tak predpokladam, že ho user nechce editovat, teda by sa mala prenasat jeho aktualna hodnota priamo, alebo pri spracovani z $values odstranit tento column(vsetky ktore su hidden), nakolko ked sa nahradi prazdnym stringom tak sa edituje spolu s ostatnymi columns bez toho aby o tom user vedel.

Editoval japijana (7. 7. 2016 9:56)

exquis
Člen | 82
+
0
-

ahoj, tak problém byl jinde – snažil jsem se používat setDefaultSort na sloupce, které jsem nevypisoval, takže se omlouvám ;)

Pavel Janda napsal(a):

Pardon, byl jsem od pc pár dní pryč, tak pojďme na to.

@exquis
1, Úplně nevím, kdy tato situace může nastat. Mohl bys připravit sandbox, kde by se toto chování projevovalo? Nebo na to narazil ještě někdo jiný? Jakou verzi datagridu používáš?

2, Vím, o co se jedná. Ano pravda, nemuselo by to házet exception. Stačilo by unsetnout hodnotu ze session. Píši si.

@Hlava
Jakou verzi používáš? Na webu dokumentace (ublaboo.org) to jede v pohodě, pokud dobře chápu tvojí situaci.

@japijana
Jaké jiné chování tě napadá? Nevím, zda by se vůbec měl pár klíč-hodnota odstranit z odeslaných $values. Ty jsi tam ten klíč vytvořil při registrace formulářového pole, tedy by se to tam mělo objevit.

David Grudl
Nette Core | 8136
+
+3
-

Hlásím, že verze 4.4.0 běží a lze instalovat úplně v pohodě pod Nette 2.4. 👍🏻

pitr82
Člen | 121
+
0
-

@PavelJanda Ahoj,
mám dotaz na group-actions.

$grid->addGroupTextAction('Add note')

Můžu nějak upravit atributy textového pole ?
Popřípadě šlo by požít i textarea (

$grid->addGroupTextAreaAction('Add note')

a pomocí class upravit velikost, pokud bych potřeboval poslat delší text?

Dík za odpověď

Pavel Janda
Člen | 977
+
0
-

@pitr82 Ahoj. Nope, teď to nelze. Ale vždycky můžeš poslat PR. :)

A nebo založit issue, no..

Pavel Janda
Člen | 977
+
+1
-

Přídána textarea u group actions, přidány volitelné class a jiné attributy u všech group acitons, viz http://ublaboo.org/…group-action#…

@pitr82, @DavidKregl

w3m
Člen | 4
+
0
-

@PavelJanda narazil jsem na stejnou chybu jako v https://github.com/…rid/pull/206, je to již opravené? Nebo něco dělám špatně? Díky!

Pavel Janda
Člen | 977
+
0
-

@w3m Mělo by to být ok již od začátku března (ze kdy je zmíněný PR). Jakou používáš verzi?

w3m
Člen | 4
+
0
-

Zkoušel jsem 4.6 i mastera. Ve chvíli, kdy ajaxově řadím záznamy, vše funguje v pořádku, ale v URL mi zůstane:

?grid-grid-sort%5BfullStreet%5D=ASC

A po refreshi stránky dostávám chybu:

[Semantical Error] line 0, col 64 near 'fullStreet A': Error: Class App\Model\Entities\Business\Customer has no field or association named fullStreet

Datagrid:

		$grid->addColumnText('fullStreet', 'Adresa')->setSortable()->setSortableCallback(function(QueryBuilder $qb, $sort) {
			$qb->orderBy('i.street', $sort['fullStreet'])->addOrderBy('i.number', $sort['fullStreet']);
		});

Po implementaci kódu z pull requestu mi funguje vše v pořádku.

Pavel Janda
Člen | 977
+
0
-

@w3m Používáš i nejnovější verzi js?

w3m
Člen | 4
+
0
-

Ano, používám :) Nevím, jestli není problém, že první argument addColumnText() u mě není sloupec v databázi – v tuhle chvíli mám pro něj pouze getter a nastavil jsem mu sortableCallback, abych se vyhnul tomu, aby se název property ve schematu vyhledával. Pokud to ale vadí, že to není přímo ve schematu, pak jsem nenašel, jak to obejít. Jinak ale, jak říkám, jsem to vyřešil copy&pastnutím kódu z toho pull requestu, což není ideální, ale funguje to.

Domki
Člen | 310
+
0
-

@PavelJanda Chtěl bych se zeptat jestli je nějaká možnost jak používat tento vypadajíc skvěle Datagrid s YetOrm

co přiřadit jako zdroj? zatím mi šlo jen YetormColekci převest na array

pak mi ale nefunguje například řazení

Nějaký elegantní řešení?

Díky

Domki
Člen | 310
+
0
-

Nyní jsem zkusil Repozitaře z YetOrmu rozšířit o IDataSource.
Ale trochu tápu jak implementovat nekteré funkce z rozhraní (sort, limit).
Nevytvářel už někdo tento DataGrid s YetOrmem?

Domki napsal(a):

@PavelJanda Chtěl bych se zeptat jestli je nějaká možnost jak používat tento vypadajíc skvěle Datagrid s YetOrm

co přiřadit jako zdroj? zatím mi šlo jen YetormColekci převest na array

pak mi ale nefunguje například řazení

Nějaký elegantní řešení?

Díky

pitr82
Člen | 121
+
0
-

@PavelJanda Mám na stránce více datagridu vytvořené jako komponenty pomocí factories. Jak mám při inline add invalidovat jen konkrétní grid?
Díky za nakopnutí.

CZechBoY
Člen | 3608
+
0
-

@Domki limit a orderBy aplikuj na vracenou instanci EntityCollection.

Domki
Člen | 310
+
0
-

@CZechBoY
Udelal jsem jednoduchou implementaci:

abstract class BaseRepository extends Repository implements IDataSource
{

	/**
	 * @var EntityCollection $data
	 */
	protected $data;

	/**
	 * Get count of data
	 * @return int
	 */
	public function getCount()
	{
		return $this->data ? $this->data->count() : $this->findAll()->count();
	}

	/**
	 * Get the data
	 * @return EntityCollection
	 */
	public function getData()
	{
		return $this->data ? $this->data : $this->findAll();
	}

	/**
	 * Filter data
	 *
	 * @param array $filters
	 *
	 * @return static
	 */
	public function filter(array $filters)
	{
		return $this->data = $this->findAll();
	}

	/**
	 * Filter data - get one row
	 * @param array $filter
	 * @return static
	 */
	public function filterOne(array $filter)
	{

		return $this->data = $this->findAll();
	}

	/**
	 * Apply limit and offset on data
	 * @param int $offset
	 * @param int $limit
	 * @return static
	 */
	public function limit($offset, $limit)
	{
		return $this->data->limit($limit, $offset);
	}

	/**
	 * Sort data
	 * @param Sorting $sorting
	 * @return static
	 */
	public function sort(Sorting $sorting)
	{
		$sort = $sorting->getSort();


		if (count($sort) === 0) {
			$array = [];
			foreach ($sort as $column => $order) {
				$array[$column] = $order == 'ASC' ? EntityCollection::ASC : EntityCollection::DESC;
			}
			$this->data = $this->data->orderBy($array);
		}
		return $this->data;
	}
}

Ale v datagridu se nevypise zadny radek a je na nem napsano : ( Items: 1 – 0 from 4 )
Co mám špatně?
a při implmentaci daného rozhraní bude následně datagrid fungovat plnohodnotně včetně všech možností?

David Kregl
Člen | 52
+
0
-

Pavel Janda napsal(a):

Přídána textarea u group actions, přidány volitelné class a jiné attributy u všech group acitons, viz http://ublaboo.org/…group-action#…

@pitr82, @DavidKregl

Super! Díky

CZechBoY
Člen | 3608
+
0
-

@Domki ja si delam v repozitari vetsinou metodu, ktera vrati objekt s kterym uz datagrid umi pracovat.
Myslel jsem teda, ze jen obalujes EntityCollection a ne celej repozitar, kterej muze mit x metod, navic ukladas data asi nekam bokem do $data promenny.

Domki
Člen | 310
+
0
-

@CZechBoY no do $data jsem ukladal nalezené kolekce nad kterými pak volam limit order..
A ta metoda ti vratí co? pole mi přijde nešikovné, a z EntityCollection na nette/database to nepřevedu ne?
Nebo ty máš implementaci pro yetOrm? Neposlal bys mi jí?
Resp proč není už v defaultu v Datagridu?

Editoval Domki (24. 7. 2016 11:18)

pitr82
Člen | 121
+
0
-

pitr82 napsal(a):

@PavelJanda Mám na stránce více datagridu vytvořené jako komponenty pomocí factories. Jak mám při inline add invalidovat jen konkrétní grid?
Díky za nakopnutí.

@PavelJanda při inline ADD musím obnovit celou stránku.

$grid->reload

mi sice pošle jen grid, ale ten ještě nemá k dispozici nová data, dájí se data znovu načíst ? Aby přidávání projevilo pěkné ajaxově i s novou hodnotou?

Pavel Janda
Člen | 977
+
0
-

pitr82 napsal(a):

@PavelJanda Mám na stránce více datagridu vytvořené jako komponenty pomocí factories. Jak mám při inline add invalidovat jen konkrétní grid?
Díky za nakopnutí.

Stejně, jako každou jinou komponentu. Komponenta nese jméno, takže například v presenteru budeš „invalidovat“ komponentu foo takto: $this['foo']->redrawControl().

Pavel Janda
Člen | 977
+
0
-

@Domki @CZechBoY S čím by měl pracovat YemORMDataSouce? S YetORM\EntityCollection? S dnbt? Klidně to napíšu, akorát potřebuji kopnout.

Pavel Kravčík
Člen | 1182
+
0
-

@Domki, @PavelJanda: Mám takový dojem, že je to neřešitelné, že EntityCollection se již nedá filtrovat kvůli lazy přístupu. Řešilo se to u Grido.

My na všech nových projektech používáme $repository->getTable() nebo pole (tak 90% pro getTable()).

pitr82
Člen | 121
+
0
-

@PavelJanda když mám jako DataSource array, tak se mi při inline editaci resp. inline add neupraví, nevloži nová data. Musím refrešnout stránku. U polí toto nefunguje jako u jiných datových zdrojů ?

Pavel Janda
Člen | 977
+
0
-

@PavelKravčík @Domki Takže v podstatě jediná věc, kterou mohu udělat je, že přidám do třídy Row nějaký property access pro YetORM\Entity (to by se použilo, pokud by tedy někdo na své straně implementoval svůj data source, který by stavěl na jakýchkoliv kolekcích s YetORM entitami).

ArrayDataSource počítá nyní s tím, že jednotlivé položky pole jsou též pole. Tedy se nepoužívá třída Row, která by zpřístupňovala zmíněný property access u různých ORM entit. To mohu změnit. ArrayDataSource může používat Row a tím pádem property access.

Jaký na to máte názor?

Pavel Janda
Člen | 977
+
0
-

@pitr82 Životní cyklus tvé instance datagridu je asi takovýto:

  1. Poslal jsi request na přidání položky
  2. Nette pozná, že požadavek míří na komponentu
  3. Zavolá se továrnička komponenty, vytvoří se instance komponenty
  4. Nastaví se datasource a všechny ostatní sloupce, filtry a podobně
  5. Továrnička vrátí komponentu
  6. Nette spustí všechny potřebné handlery v komponentě
  7. Tak, teď bohužel nestačí pouze překreslit komponentu (data source už je nastaven a jelikož se jedná o pole, nic se netahá „líně“ z databáze až na poslední chvíli). Takže si můžeš buď vytvořit nějaký lazy data source, nebo znovu přiřadit data source datagridu.
Pavel Kravčík
Člen | 1182
+
0
-

@PavelJanda: Mně to přijde zbytečná práce, aby fungovalo jen následující, což u nás považujeme za docela „prasárnu“ – nemá to prakticky žádný význam a pro větší tabulky je to pomalejší. Sice je to trochu znásilnění principu ORM, ale v tomhle případě je ORM nevhodné. :)

// Ošklivý přístup
$grid->setModel($repository->findAll()->toArray());

// Lepší přístup
$grid->setModel($repository->getTable());

//YetORM/Repository rozšíření
public function getTable($table = NULL)
{
	return parent::getTable($table);
}
Pavel Janda
Člen | 977
+
0
-

@PavelKravčík Dobře, tak já nic dělat nebudu. :D
Souhlas, ta table fungovat bude.

Domki
Člen | 310
+
0
-

@PavelKravčík
A vy používáte YetOrm s Datagridem jo?

Dík za nastin. Jen dotaz tím setModel je na mysli setDataSource, nebo to je nejaka vaše speciální funkce?

Kdyz jsem do datasource nastavil $repository->getTable(), tak datagrid funguje super, aj s strankováním.
Jen mám dotaz, jak řešíte volaní funkcí z entit? V entitach mám funkce například na ziskat Authora podle id, připadne získaní zaznamu pres vazební tabulky.
Např:

$grid->allowRowsAction('delete', function ($item) {
			return $item->getProductsWithBrand()->count() === 0;
		});

mi vraci chybu ze funkce getProductsWithBrand není definovana.

Díky

Editoval Domki (27. 7. 2016 23:02)

romiix.org
Člen | 343
+
0
-

Napadlo mi zjednodušenie definície small inline edit, ale neviem či s tým nie sú nejaké problémy ktoré nevidím.

Pre small inline edit by bolo použiteľné aj:

$grid->addColumnText('name', 'Name')
	->setEditable();

$grid->addInlineEdit()
	->onControlAdd[] = function($container) {
		$container->addText('id', '');
		$container->addText('name', '');
		$container->addText('inserted', '');
		$container->addText('link', '');
	};

$grid->getInlineEdit()->onSetDefaults[] = function($container, $item) {
	$container->setDefaults([
		'id' => $item->id,
		'name' => $item->name,
		'inserted' => $item->inserted->format('j. n. Y'),
		'link' => $item->name,
	]);
};

$grid->getInlineEdit()->onSubmit[] = function($id, $values) {
	/**
	 * Save new values
	 */
};

Pre formulár by sa použil automaticky form contajner nastavený pre daný stĺpec z big inline edit a ak by nebol nastavený vlastný callback, použil by sa $grid->getInlineEdit()->onSubmit[] s nezmenenými dátami z $item, iba s modifikovanou tou jednou konkrétnou hodnotou, ktorá je menená.

Čo myslíte? Je to dobrý nápad?

Hlava
Člen | 19
+
0
-

@PavelJanda
Zdravím, jak to vypadá s validací inputu v případu povinných položek v inlineAdd? Podařilo se Vám to nasimulovat nebo mám chybu někde já? Bude se to řešit nebo to mám řešit sám?

Domki
Člen | 310
+
0
-

K inline editaci a přidávání bych měl takový dotaz.
Je nějak možné použit inline editaci/add u datagridu s řazením nebo tree-view?

Díky

Pavel Janda
Člen | 977
+
0
-

@Domki Asi je. Zkus to a uvidíš, není nic jednoduššího. :) Nebo máš na mysli konkrétní situaci?

Editoval Pavel Janda (28. 7. 2016 22:10)

Šaman
Člen | 2635
+
0
-

Ahoj, zkouším poprvé tento grid – čistá instalace composerem a bowerem na web-projectu s Nette 2.3.
A když přejdu na stránku s gridem (bez parametru), naskočí mi poslední stránka v gridu, kde jsem byl naposled. Nikoliv první stránka, jak bych očekával. Při dalším stránkování se už stránka dostává i do adresy, to je v pohodě. Toto chování je stejné při ajaxu i bez něj.
Je to feature, je to bug?

Pavel Kravčík
Člen | 1182
+
+1
-

@Domki: Tam právě nevstupuje entita, ale ActiveRow (https://doc.nette.org/…ase/explorer). Takže takhle funkce je „nedostupná“. Případně by to šlo obejít možná nějak takto:

->setRender(function($row)
{
	$entity = new Entity($row);
	return $entity->customFunction();
})

Editoval Pavel Kravčík (29. 7. 2016 7:58)

Pavel Janda
Člen | 977
+
0
-

@Šaman Ano, datagrid si pamatuje sort, page, per page, hidden columns, filtry… Lze mu říci, aby si to nepamatoval.

Pokud taková funkcionalita nestačí, lze založit issue „aby si datagrid nepamatoval pouze page“ při pamatování věcí skrze session a nebo rovnou poslat stejnojmenný PR. :D

Nechám si projít hlavou plusy a mínusy obou variant.

Šaman
Člen | 2635
+
0
-

Pavel Janda napsal(a):

@Šaman Ano, datagrid si pamatuje sort, page, per page, hidden columns, filtry… Lze mu říci, aby si to nepamatoval.

Pokud taková funkcionalita nestačí, lze založit issue „aby si datagrid nepamatoval pouze page“ při pamatování věcí skrze session a nebo rovnou poslat stejnojmenný PR. :D

Nechám si projít hlavou plusy a mínusy obou variant.

Aha, a má ty parametry zobrazit v URL? Protože mě mate, že když přijdu na stránku s Gridem, je už nějak nastavený, ale v URL to není zmíněno. Takže by se mohlo i stát, že zkopíruji adresu a někomu ji pošlu, ale jemu se zobrazí úplně jiná data. Nevím ale, jestli není chyba u mě (že to napoprvé není v adrese).
Když pak ručně přejdu na nějakou stránku, tak se to do URL předá, to už je v pohodě.

Pavel Janda
Člen | 977
+
0
-

@Šaman Ano, to je standardní chování. Datagrid si pamatuje v session fitry, stránkování apod (dále jen filtry) a pokud přijdeš na stránku s tímto datagridem, filtry se obnoví. Teprve potom se mohou na stejné stránce propisovat do URl persistentní parametry (V případě, že datagrid používá ajax, propisuje se state presenteru do url pomocí history API).

Jak bys to řešil? Budu rád za spásný nápad. :)

Pokud si má datagrid ukládat do session aktuální stav, nelze nijak jednoduše změnit rovnou url při příchodu na stránku s datargidem, který má již tyto informace v session. Musel by se předávat nějaký JS objekt state z PHP do JS a pak pokaždé kontrolovat, zda není náhodou tento objekt „neprázdný“ a url prázdná..

Jiné řešení mě teď nenapadá a tohle se mi nelíbí.

Danndy
Člen | 35
+
0
-

@PavelJanda Ahoj, Naozaj super datagrid! Palec hore! Mal by som ale dve otázočky.

Keď som si skúšal tvoj datagrid a hral sa trocha s url, ktorá obsahovala nejaký sorting parameter (napr.: &doctrineGrid-sort[name]=DESC) a zmenil som „name“ na nieco ine (nesprávne) išlo to hneď do error 500. Je to niečo s čím by som si mal lámať hlavu?

Druhá otázka: Používam Doctrine 2 pre DataSource, a chcem v datagride zobraziť záznamy z tabulky „article“ ale aj spolu s kategóriou do ktorej su priaradene (ManyToOne). Je možne pre takýto stĺpec pridať FilterMultiSelect podla názvu kategórie? resp. Je možne v datasource použiť join a pracovať s join-utými entitami?

Ďakujem.

Pavel Janda
Člen | 977
+
0
-

@Danndy Díky.

  1. No pokud jsi změnil název sloupce, datagrid se bude snažit najít neexistující sloupec, aby podle něj mohl setřídit data.. To je prostě chyba. Mohl bych přidat nějaký „silent-mode“, pokud by byl zájem. Potom by to prošlo. Sice nejsem úplně přesvědčen, že je to správná cesta, ale budiž. Pokud se bojíš, že bude uživatel přepisovat url a nechceš mu ji dát k dispozici, můžeš vypnout přepis url a nechat datagrid tiše pracovat pouze se session ($grid->setRefreshUrl(FALSE);).
  2. DoctrineDataSource normálně iteruje nad entitami, takže tam můžeš vypisovat jakkoliv složité vazby. A nebo si v šabloně volat sám metody entit. A nebo ještě několika způsoby. :D
Danndy
Člen | 35
+
0
-

@PavelJanda Díky za rýchlu odpoveď.

  1. Máť parametre filtrov/sortov v url je fajn vec. Viem, že si každý povie „kto by sa už len hrabal v url“ ale možno stojí za zváženie do budúcna, aby datagrid kontroloval či je stlpec pre sortovanie definovaný.
  2. Takto nejak to mám:
<?php
 $grid->setDataSource($qb->select('a, c')->from('App\Entity\Article', 'a')->leftJoin('a.category' ,'c'));

 ...

 $grid->addColumnText('category', 'Kategória', 'category.name')
        ->setSortable('c.name')
        ->setFilterMultiSelect($this->categoryFacade->getCategoryPairs())
        ->setCondition(function($fluent, $value) {
          	$fluent->where('c.id IN(:arr)')->setParameter('arr',implode(",", $value));
        });
?>

Je aj to „prípustne riešenie“ ? alebo je niektore lepšie?

Pavel Janda
Člen | 977
+
0
-

@Danndy Můžeš na to založit issue? Úprava by neměla být velká.

A bez té custom condition ti filtrování nefunguje? Funkcionalita by měla být nativně stejná.. (DoctrineDataSource::applyFilterMultiSelect()). Asi bude potřeba, abys definoval sloupec, který se má použít při vyhledávání. Takže by mělo stačit něco takového:

$grid->addColumnText('category', 'Kategória', 'category.name')
    ->setSortable('c.name')
    ->setFilterMultiSelect($this->categoryFacade->getCategoryPairs(), 'c.id');
Danndy
Člen | 35
+
0
-

@PavelJanda

2. Dík moc krát, tvoj kód funguje :)

1. Áno, môžem vytvoriť. Ked som si prechádzal kód, dalo sa to oŠetrit jednou podmienkou vo funkcii DataGrid->createSorting(…); Hneď ma ale napadla jedna otázka, podporuje DataGrid aj sorting podľa viacerých stĺpcov naraz?

Editoval Danndy (4. 8. 2016 16:06)

Pavel Janda
Člen | 977
+
0
-

@Danndy Nepodporuje, zatím.

ramaskrik
Člen | 3
+
0
-

Zdravím,
s Nette ešte len začínam, takže možno to bude taká noob otázka.

Stiahol som si ublaboo cez composer a hodil podľa oficiálneho tutoriálu kód do presenteru.
Ako mám teraz vložiť datagrid do šablóny? render() to asi nebude, čo?

public function renderDefault()
{
    $this->createComponentGrid('authorizations')->render();
}

public function createComponentGrid($name)
{
    $grid = new DataGrid($this, $name);

    $grid->setDataSource($this->database->table($name)->order('id DESC'));

    $grid->addColumnText('phone', 'telefón');
    $grid->addColumnText('code', 'kód');
}

Editoval ramaskrik (4. 8. 2016 17:08)

romiix.org
Člen | 343
+
+1
-

Do šablóny sa vloží komponenta sama – použi ju rovno v šablóne.

{control grid}

ramaskrik napsal(a):

ramaskrik
Člen | 3
+
0
-

Kudos to you, romiix, za rýchlu odpoveď!

Hm, ja som tam skúšal predtým dávať datagrid namiesto grid. Kde som mal zistiť, čo to má byť? V dokumentácii som to nenašiel, prehliadol som to?

Editoval ramaskrik (4. 8. 2016 17:28)

CZechBoY
Člen | 3608
+
+3
-

@ramaskrik createComponentXXX($name), kde XXX je jméno pro makro control, případně v $name ti přijde to jméno taky.

Editoval CZechBoY (4. 8. 2016 17:39)

ramaskrik
Člen | 3
+
0
-

@CZechBoY vďaka. Aj keď to asi patrí skôr do začiatočníckeho fóra. Ale pomohlo to :)

romiix.org
Člen | 343
+
+1
-

Use case

V detaile položky zobrazujem formuláre s nastaveniami položky. Veľmi rozsiahle, podelené v taboch. Je to výborne použiteľné, pretože je takto možné ovládať takmer celú aplikáciu z jedného gridu.

Problém

Takto načítané formulárové komponenty nepracujú korektne, pretože ide o formulár vo formulári.

Komponenta <form> filter obaľuje celý grid od začiatku po koniec.

Riešenie

Rozdeliť formulár na:

  • filter
  • groupAction
  • add
  • edit
  • perPage

Chcekboxy pre hromadné akcie by boli riešiteľné pripojením k formuláru atribútom form. Žiaľ, vyžadovalo by to JS fix pre IE/Edge.

Záver

Čo na to vravíte? Hlavne @PavelJanda