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

CZechBoY
Člen | 3608
+
0
-

Neslo by v nette db nastavit count na

$selection->getName() . '.' . $selection->getPrimary()
Šaman
Člen | 2635
+
0
-

Pavel Janda napsal(a):

@Šaman Tak by to jistě šlo. Tedy jich udělám 10. Jenže pak bude chtít někdo 15% šířku. Tak se přidá dalších 10. Pak bude chtít někdo 17,5%. :D Atp.

Bral bych to jako poslední možnost.

Takhle jsem to nemyslel. Měl jsem na mysli něco jako

<?php
$grid->addColumnText('name', 'Name')
	->addAttribute('class', 'moje_super_trida');
?>

Ať si každý nadělá třídy jaké chce.

Editoval Šaman (2. 3. 2016 20:45)

Pavel Janda
Člen | 977
+
0
-

@Šaman Jo takhle. To je lepší varianta.

Pavel Janda
Člen | 977
+
0
-

@CZechBoY Mrknu na to, dík.

sibka
Člen | 24
+
0
-

Díky za super grid. Jen mám jeden zádrhel. I ve tvém demu mi v IE nefungují věci okolo checkboxů. V jiných prohlížečích problém není. Jen ten IE zlobí.

  • při zaškrtnutí se Group actions zůstávají zašedlé/nepřístupné
  • checkbox „Select All“ neovlivní žádný řádek gridu
  • vzhled „happy“ je deformován (místo „fajfky“ jsou jen dvě čárky)

V souboru libraries.js mi to vyhazuje Objekt tuto akci nepodporuje (return i=„svg“===t.target.tagName?t.target.parentNode:„rect“===t.target.tagName?t.target.parentNode.parentNode:t.target,i&&i.classList.contains(„happy-checkbox“)?(t.preventDefault(),s=‚input[type=checkbox][name=„‘+i.getAttribute("data-name“)+‚„]‘,n=document.querySelector(s),n?(i.classList.contains("active“)?(n.checked=!1,i.classList.remove(„active“)):(n.checked=!0,i.classList.add(„active“)),e=new Event(„change“,{bubbles:!0}),n.dispatchEvent(e)):void 0):void 0}).

Pavel Janda
Člen | 977
+
0
-

@sibka Díky za report. Mrknu na to večer. Snad se mi podaří někde sehnat komp s Win. :D
Můžeš mi pls poslat verzi IE, ve které jsi na to narazil?

sibka
Člen | 24
+
0
-

IE 11, díky.

Pavel Janda napsal(a):

@sibka Díky za report. Mrknu na to večer. Snad se mi podaří někde sehnat komp s Win. :D
Můžeš mi pls poslat verzi IE, ve které jsi na to narazil?

Pavel Janda
Člen | 977
+
+1
-

@exquis @Šaman Verze v2.2.0 přidává renderování elementů th a td pomocí Nette\Utils\Html. Je možné k těmto elementům přistupovat:

$th = $grid->addColumnText('name', 'Name')
	->getElementPrototype('td'); // Nebo element <td> pomocí Column::getElementPrototype('td')

$th->data('foo', 'bar');
$th->class('super-column')

Nebo je možné nastavovat atributy pro oba elementy najednou:

$grid->addColumnText('name', 'Name')
	->addAttributes(['class' => 'text-center']);

@CZechBoY Přidáno, díkes za tip.

exquis
Člen | 82
+
0
-

Pavel Janda napsal(a):

@exquis @Šaman Verze v2.2.0 přidává renderování elementů th a td pomocí Nette\Utils\Html. Je možné k těmto elementům přistupovat:

$th = $grid->addColumnText('name', 'Name')
	->getElementPrototype('td'); // Nebo element <td> pomocí Column::getElementPrototype('td')

$th->data('foo', 'bar');
$th->class('super-column')

Nebo je možné nastavovat atributy pro oba elementy najednou:

$grid->addColumnText('name', 'Name')
	->addAttributes(['class' => 'text-center']);

@CZechBoY Přidáno, díkes za tip.

Perfektní, díky moc

exquis
Člen | 82
+
0
-

Tak další postřeh, aktualizoval jsem na v2.2.0 a změna funkce getCount() na

$selection->getName() . '.' . $selection->getPrimary();

ukázala další problém a to ve chvíli, kdy využíváte v MySQL pohledy. Jelikož se data_source snaží brát dle primárního klíče a pohled žádný primární klíč nemá, tak vyhodí chybu. S normální tabulkou běhá perfektně.

Pavel Janda
Člen | 977
+
+1
-

@exquis v2.2.1, thanks.

exquis
Člen | 82
+
+1
-

Možná se to někomu bude hodit – při provádění hromadných akcí (konkrétně změna stavu objednávky, kdy se odesílají i emaily), kdy akce trvá nějakou dobu, to díky ajaxu vypadá, že se nic neděje a nezkušený uživatel nepozná může na tlačítko potvrzení hromadné akce kliknout znovu. Tomu jde zabránit jednoduchým skriptíkem:

$.nette.ext('callbacks', {
     start: function () {
        $("#group_action_submit").after("<span class='mass-action-confirmation'><i class='fa fa-spin fa-2x fa-spinner'></i> čekejte prosím, pracuji... </span>");
    },
    complete: function () {
        $(".mass-action-confirmation").hide();
    }
	})

	CSS:
	.mass-action-confirmation i{position:relative; top:5px; left:5px; margin-right:10px; color:black}

EDIT: upraveno i s odstraněním

Editoval exquis (3. 3. 2016 12:29)

Pavel Janda
Člen | 977
+
0
-

@exquis Super nápad. Sice ti tam chybí odstranění spinneru po success eventu, ale píšu si issue „navázat volitelné spinnery na ajaxové akce“. :)

exquis
Člen | 82
+
+1
-

Pavel Janda napsal(a):

@exquis Super nápad. Sice ti tam chybí odstranění spinneru po success eventu, ale píšu si issue „navázat volitelné spinnery na ajaxové akce“. :)

Většina akcí u mě končila redirectem, takže mi to nedošlo, upraveno ;)

CZechBoY
Člen | 3608
+
0
-

@PavelJanda np, ale getPrimary() může vracet pole více sloupečků ;-)
sorry :D

Pavel Janda
Člen | 977
+
0
-

@CZechBoY Jeez.

No, musím trochu na podpoře složených klíčů zapracovat.

Jo a nesouhlasím s tím. :D Pokud budu chtít primary key (::getPrimary()) po NDBT, nedá mi pole cizích klíčů. Začne na mě křičet, že mi teda nic dát nechce:

Table 'a' does not have a primary key.

Edit: cache..

Editoval Pavel Janda (3. 3. 2016 16:34)

CZechBoY
Člen | 3608
+
0
-

@PavelJanda Bude vracet pole pokud je definován primární klíč na více sloupcích.

Pavel Janda
Člen | 977
+
+1
-

@CZechBoY v2.2.4

Arty
Člen | 3
+
+1
-

Ahoj,
líbí se mi tvůj přístup a rychlost vývoje. Plánuješ do gridu přidat i inline editování?

Každopádně tomuto gridu fandím!

Pavel Janda
Člen | 977
+
+1
-

@Arty Zatím je podporována taková malá inline editace, kde se prostě zavolá callback s novou hodnotou a primárním klíčem. Je to rychlé a popsané v docu.

Velkou inline editaci přes celý řádek plánuji, byť mám na pořadu dne věci, kterým přikládám vyšší prioritu (ColumnStatus a animované spinnery – viz issues na githubu).

Do konce týdne bych mohl mít hotové výše zmíněné, tak se pak pustím do té větší inline editace. Už tam leží delší dobu, pravda. :)

Editoval Pavel Janda (4. 3. 2016 9:00)

sibka
Člen | 24
+
0
-

v2.2.4:
hlásí chybu v souboru NetteDatabaseTableDataSource.php:63 source ► reset(arguments ►) – reset() expects parameter 1 to be array, string given

Primární klíč mám výchozí, tedy „id“

Pavel Janda
Člen | 977
+
0
-

@sibka To jsem to ale oslík, pořadí vyhodnocování operátorů mě přechytračilo. Fixed, updatni composer..

sibka
Člen | 24
+
0
-

@PavelJanda Super, už to šlape. Díky :-)
Nedíval ses prosím na ten IE?

Pavel Janda
Člen | 977
+
+1
-

Mám to v úkolníčku. Bohužel jsem se nedostal ani k Win kompu, ani k rozjetí virtualboxu. O víkendu :)

Pavel Janda
Člen | 977
+
+4
-

Nová verze – v2.3.0

  • Přidán script (datagrid-spinners.js) s nette.ajax.extension. Tento script bude zobrazovat u některých ajaxových akcí spinnery. Více zde.
  • Přidán sloupec ColumnStatus. Vykreslí bootstrap dropdown, takže pokud ho chcete používat, je třeba bootstrap.js. Více zde.

Na pořadu dne je velká inline editace a fluent interface pro okamžité nastavení stejnojmenného filtru sloupce (jako to znáte z jiných gridů: $grid->addColumn()->setFilter()).

Editoval Pavel Janda (7. 3. 2016 11:43)

Pavel Janda
Člen | 977
+
0
-

@sibka Konečně díval. Fixnul jsem event dispatching pro IE, ale bohužel, Explorer neumí rotovat elementy v svg, takže jsou ty checkboxy rozsypané.

Zkusím nahradit rotovaný <rect> širokou čárou. To by asi mohlo zafungovat.

sibka
Člen | 24
+
0
-

@PavelJanda Díky, happy nemusím používat, hlavní je, že už ty checkboxy fungují.

pitr82
Člen | 121
+
0
-

Mám sloupec s referenci @ManyToOne a nejde mi podle tohoto sloupce řadit.
Entita User

	/**
 * Vazba role N:1 na sysRole.
 * @ORM\ManyToOne(targetEntity="SysRole")
 * @ORM\JoinColumn(name="sysRole_id", referencedColumnName="id")
 */
protected $role;

Zobrazení mi jde vpohodě

$grid->addColumnText('role.name','Role uzivatele')
		->setSortable();

Ale nejde mi podle něj třídit.
Všiml sem si, že už to tady řešil @Hurass.

Pokud udělám stejný dotaz jako @Hurass a dám:

$grid->addColumnText('role2','Role uzivatele','ur.name')
		->setSortable();

Tak dostanu chybu: Cannot read an undeclared property App\Model\Entities\SysUser::$ur

$grid->addColumnText('role2','Role uzivatele','role.name')
		->setSortable();

Tak mi to zase vyhodí špatný dotaz.

SELECT u
FROM App\Model\Entities\SysUser u
LEFT JOIN App\Model\Entities\SysRole ur WITH ur.id = u.role
ORDER BY role.name ASC

Jak to tedy donutit řadit?

Používám master.

Dík za nakopnutí

Editoval pitr82 (8. 3. 2016 1:56)

Hurass
Člen | 114
+
0
-

@pitr82 ukaž jak předáváš QueryBuilder do datagridu.
Já tam mám toto:

$grid->setDataSource(
    $this->userRepository->createQueryBuilder("u")
        ->leftJoin(\App\Model\UserRole::class, "ur", \Kdyby\Doctrine\Dql\Join::WITH, "ur.id = u.userRole")
);

Jinak můj příklad funguje bez problému.

Editoval Hurass (8. 3. 2016 7:19)

pitr82
Člen | 121
+
0
-

@Hurass
dokonce jsem to přepsal podle tebe.

$this->em->getRepository(SysUser::class)->createQueryBuilder('u')
		->leftJoin(\App\Model\Entities\SysRole::class, "ur", \Kdyby\Doctrine\Dql\Join::WITH, "ur.id = u.role");

Mám tady problem u tohoto:

$grid->addColumnText('role2','Role uzivatele','ur.name')
        ->setSortable();

Tak dostanu chybu: Cannot read an undeclared property App\Model\Entities\SysUser::$ur

Editoval pitr82 (8. 3. 2016 10:33)

Pavel Kouřil
Člen | 128
+
0
-

Hmm, tak jsem jej konečně pořádně otestoval a použil, upravil si šablony aby seděly k šabloně (metronic) a datepickeru co používáme, a narazil jsem na následující:

  • dají se nějak líp změnit šablony filtrů než si dělat vlastní fork? je to popravdě docela nepraktické
  • pamatování filtrů a řazení v session je supr věc, ale v momentě co má člověk více datagridů, skládá to queries špatně; lze nějak nastavit název datagridu který by sloužil jako session „namespace“ a tedy každý datagrid by měl vlastní „paměť“?
  • jak dostat přes vlastní render do sloupce HTML?

Jinak skvělá práce!

PS: Doporučoval bych vypsat závislosti i jinak než v boweru (stačí linky na knihovny v README/dokumentaci), ať člověk může datagrid jednoduše použít i bez něj. Nejhorší bylo dohledání happy.js. :)

Pavel Janda
Člen | 977
+
0
-

@pitr82 Můžeš pls zkusit master?
Totiž:
1, datagrid si bere tečkovou notaci jako přístup k objektům, což je žádoucí chování, abys mohl při výpisu dat přistupovat k objektům.
2, Pokud se sortí, nešel do teď nastavit sloupec pro řazení, který by používal alias (pokud chceš vypisovat data pomocí $navazany_objekt->property).
3, Měj nastavený grid tak, jak jsi psal v prvním komentáři, ale přidej:

$grid->addColumnText('role2','Role uzivatele','role.name')
	->setSortable('ur.name')

Editoval Pavel Janda (8. 3. 2016 11:47)

Pavel Janda
Člen | 977
+
0
-

@PavelKouřil
1, Ano: $filter->setTemplate(...) (Je to v docu)
2, Jakou používáš verzi? Každý DataGrid si skládá data do vlastní session. Je to ukázané například na úvodní stránce na webu (dolní grid je ale jen stránkovaný), nebo na stránce filter (oba jsou filtrované a do vlastní session).
3, $column->setTemplateEscaping(FALSE) (Je to v docu)

PS: Jo díky, dám tam i jiný způsob načítání assetů, než přes bower.

Editoval Pavel Janda (8. 3. 2016 11:49)

pitr82
Člen | 121
+
0
-

@PavelKouřil
Super, funguje :-)

Pavel Janda
Člen | 977
+
0
-

@pitr82 Ok, otagováno (v2.3.3)

harmim
Člen | 26
+
0
-

@PavelJanda Jak máš v dokumentaci napsané

<!-- Use this little extension for ajax spinners -->
<script src="../bower_components/ublaboo-datagrid/assets/dist/datagrid-spinners.js"></script>

tak bys tam ještě mohl doplnit, že je potřeba si nalinkovat datagrid-spinners.css.

Pavel Janda
Člen | 977
+
0
-

@harmim Kruci já už to dal do souboru vedle a zapomněl jsem to zdokumentovat. Děkuju.

Pavel Kouřil
Člen | 128
+
0
-

Pavel Janda napsal(a):

@PavelKouřil
1, Ano: $filter->setTemplate(...) (Je to v docu)

No, a nějak „globálně“? Aby každý „FilterDateRange“ používal ve výchozím nastavení můj template? U gridu to mám vyřešené tak, že mám prostě grid factory, která jej konfiguruje – ale filtr takto nemůžu ovlivnit, ne?

2, Jakou používáš verzi? Každý DataGrid si skládá data do vlastní session. Je to ukázané například na úvodní stránce na webu (dolní grid je ale jen stránkovaný), nebo na stránce filter (oba jsou filtrované a do vlastní session).

Verzi používám v2.2.5 – a dokonce ty dva gridy nejsou na jedné stránce, ale jsou vytvořený v naprosto jiných presenterech, a stejně tam ta kolize vzniká. Jak se tedy grid rozhoduje ke kterému gridu uložené data v session patří?

3, $column->setTemplateEscaping(FALSE) (Je to v docu)

Omlouvám se, todle jsem přehlédl :) díky, funguje!

Pavel Janda
Člen | 977
+
0
-

@PavelKouřil
1, No že by se mi chtělo používat pro templaty filtrů statické proměnné, to se říct nedá.

Buď tedy můžeš extendit DatagGid::addFilterDateRange, nebo to nějak pošolíchat s Nette\Object::extensionMethod, ale to je dost kekel.

Máš nějaký jiný nápad, jak to tam držet i „globálně“ a přesto hezky/šikovně?

2, Aha, no bere se jméno komponenty. Takže pokud se datagridy jmenují stejně, asi tam může nastat kolize. Ale nevím, jestli se mi chce psát issue. Mohu mít dva usersGridy v různých částech appky a chtít stejné session úložiště.. Naopak se mi líbí víc toto chování.

LeonardoCA
Člen | 296
+
0
-

ad 2. podle mne je logictejsi, praktictejsi a min WTF pouzivat jedinecny identifikator pro ulozeni stavu a je na to jednoduchy fix – viz Nette\Application\UI\PresenterComponent->getUniqueId()

v tvem DataGridu:

<?php
  /**
    * Find some unique session key name
    * @return string
    */
   public function getSessionSectionName()
   {
       //return $this->getPresenter()->getName().':'.$this->getName();
       return $this->getUniqueId();
   }
?>

Editoval LeonardoCA (9. 3. 2016 13:47)

Pavel Janda
Člen | 977
+
0
-

Mýlil jsem se, Jak je napsáno výše, za klíč session section se považuje <Jméno presenteru>:<jméno komponenty>.

@LeonardoCA $this->getUniqueId() je nedostatečné.

@PavelKouřil Tím pádem je klíč session dat datagridu určitě unikátní. Můžeš pls zkontrolovat, že pod jakým klíčem se ti ukládají session? například pomocí kdyby/nette-session-panel (fajn tool pro debugování session dat).

Editoval Pavel Janda (10. 3. 2016 0:04)

Martk
Člen | 655
+
+2
-

@PavelJanda Co takhle nahradit getName za getUniqueId, kvůli vnořeným komponentám?

Attanon
Člen | 25
+
0
-

Hoj, v první řádě musím pochválit. Protože tento grid je fakt super!

a chtěl jsem se zeptat, jestli je možné využít tree-view s datasource z doctrine. Pokud jo, tak můžete mě prosím nasměrovat jak to nastavit? datasource a setTreeView.

Pavel Janda
Člen | 977
+
0
-

@Attanon Jsou potřeba víceméně 2 jiné queries.

1, $grid->setDataSource($q1): Query, která získá top-level rodiče
2, $grid->setTreeView([$this, 'getChildren'], 'has_children');: $this->getChildren dostane jako parametr $parent_category_id – s tímto parametrem a nějakou další query vrátíš potomky toho žádaného rodiče
3, has_children – druhý parametr metody setTreeView je nějaký „truthy“ sloupec, který určuje, zda mají položky potomky či nikoliv. Buď je to sloupec, nebo to taky může být callback, který bude vracet true/false (dostane tu item jako argument)

Kdybys to chtěl v konkrétním příklady, tak až přijdu domu, pošlu ti ukázku s doctrine.

Attanon
Člen | 25
+
0
-

@PavelJanda Děkuji za info. Není potřeba ukázku, už se mi to povedlo rozjet. Já tam ty potomky už posílal. Ale špatně. Nedošlo mi, že to musí být queryBuilder stejně jako datasource.

Attanon
Člen | 25
+
0
-

@PavelJanda ještě otázečku malou. Je možné změnit ty chevron ikony u toho treeview? Namapovat to na nějaké jiné?

P.S. Lze změnit ikony ostatní ze spanu na i?

Editoval Attanon (10. 3. 2016 19:04)

Pavel Janda
Člen | 977
+
0
-

@Attanon Už ano. v2.3.8

1, Nastav datagidu vlastní šablonu:

$grid->setTemplateFile(__DIR__ . '/a.latte');

2, V šabloně poděď původní šablonu a přepiš {block chevron-icon}:

{extends dirname($original_template) . '/datagrid_tree.latte'}

<i n:block="chevron-cion" class="{$icon_prefix}user"></i>
Pavel Janda
Člen | 977
+
0
-

@Attanon Koukám, že je tam občas <i> a občas <span>. Sjednotím to na i.

Edit: composer update

Editoval Pavel Janda (10. 3. 2016 20:15)

Attanon
Člen | 25
+
0
-

@PavelJanda děkuji mockrát. Ještě bych tě ale poprosil, jestli by bylo možné upravit ten sortable button ($grid->setSortable();) aby se mohla upravovat ikonka.

sepo
Člen | 69
+
0
-

Ahoj
je možné pri zmene zoradenia na stĺpci resetovať paginator (skočiť) na prvú stranu ?

P.S.:
„good job“