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

chladekt
Člen | 10
+
0
-

@PavelJanda Opožděně reaguji k problému ke 2 gridům na 1 stránce. Iframe mi přijde jako komplikované řešení. Na jedné stránce jsem to pořešil tak, že jsem pro ty gridy vypnul ajax, takže se refreshuje celá stránka. Na druhé stránce mi to nedělá – nejspíš proto, že ty tabulky mají různé sloupce.

pp
Člen | 50
+
0
-

Ahoj,
mam sloupec ve kterem bych potreboval filtrovat hodnoty vyberem v selectu ale ne presnou hodnotou ale podminkou (treba rozsahem – vyberem SKUPINA_A (< 100), SKUPINA_B (101–1000), SKUPINA_C (> 1000). Necha se to resit nejakou filtrovaci funkci ? Dekuju

Pavel Janda
Člen | 977
+
0
-

@pp Asi bych si připravil vlastní podmínku… https://contributte.org/…filters.html#…

pavel_4
Člen | 13
+
0
-

Ahoj, dá se někde v komponentě (nebo v šabloně) dostat k vyfiltrovaným položkám?

Vysvětlím – mám vlastní hromadné operace, které fungují dobře, mám tlačítko vybrat vše na stránce, které je taky ok, ale potřebuju udělat checkbox „vybrat vše vyfiltrované“. Chtěl jsem po kliku na tento checkbox získat pole všech hodnot primárního klíče všech vyfiltrovaných záznamů (ID), ale to se mi nedaří.

Když se podívám do data source, kde je QueryBuilder, tak obsahuje všechny položky (bez filtru). Jde to řešit? Zkoumal to už někdo?

chladekt
Člen | 10
+
0
-

@PavelJanda Když teda chci mít 2 gridy se stejnými sloupci na jedné stránce a jejich konfliktům chci zabránit vypnutím AJAXu (může být vypnutý na celé stránce, ale na jiných stránkách ho mám zapnutý), tak nejjednodušší způsob je odstranit ze vsech trid v těch gridech ajax? Zkoušel jsem také nevkládat nette.ajax.js, ale pak mi jiné js soubory házely chyby (třeba datagrid.js).

milos
Člen | 1
+
+1
-

Ahoj,
lze nějak nastavit Datagrid tak, aby u něj byla editovatelná pole rovnou editovatelná? Tzn. bez nutnosti kliku do daného pole, případně kliku na tlačítko (akce), které přemění pole na editovatelné?

Příklad:
Mám sloupec „Počet ks“, který je editovatelný. Současné řešení je takové, že uživatel musí nejprve kliknout na pole a teprve pak může upravit hodnotu. Mně by se hodilo, kdyby pole bylo editovatelné rovnou – „ve stavu Uprav hodnotu“ – bez nutnosti kliku.

Předem mockrát díky za jakoukoli radu!

Pavel Janda
Člen | 977
+
+1
-

@milos To teď grid neumí, ale je to zajímavý nápad na PR. 👍

magenzajin
Člen | 9
+
0
-

Ahoj vše!
Chci v rámci jednoho gridu vzít z jiné tabulky client sloupec email. Vidím to na NetteDatabaseTableDataSource.
Takže do gridu toto:
$grid->addColumnText(‚email‘, ‚Email‘, ‚:client‘);
Jak by ale měla vypadat funkční implementace..?? v rámci třídy i v rámci metody
public function createComponentGrid($name) ???
Omluvte začátečníkovu neznalost.
Díky!

Editoval magenzajin (17. 6. 2019 15:19)

Pavel Janda
Člen | 977
+
0
-

@magenzajin

Třaba takto:

namespace MujNapespace;

use Nette\Database\Context;

class NejakyPresenter
{

	/**
	 * @var Context
	 * @inject
	 */
	public $context;


	public function createComponentGrid(): DataGrid
	{
		$grid = new DataGrid;

		$grid->setDataSource($this->context->table('client'));

		$grid->addColumnText('email', 'Email', 'client');

		return $grid;
	}
}

A nebo se inspiruj dalšími příklady zde: https://github.com/…tte-datagrid
Všechny příklady jsou reálně – běží jako demo zde: https://examples.planette.io/…te/datagrid/

Editoval Pavel Janda (17. 6. 2019 16:46)

magenzajin
Člen | 9
+
0
-

Dík. To vypadá gut,ale co s tímhle pak: There is already action at key [email] defined… Dík

Pavel Janda
Člen | 977
+
0
-

@magenzajin Nejspíš definuješ dvě akce na satejném klíči. Budeš tam mít něco jako

$grid->addAction('email', ....);
$grid->addAction('email', ....);
magenzajin
Člen | 9
+
0
-

Takhle vypadá kód před refractoringem. Taskem je přidat email z tabulky client. Přičemž datasource je nyní PricelistHistoryRepository. Je to dosti rozmrvený kód. Přičemž by to mělo být cajk. Máme jeden table pricelists_history a table client. V té první máme user_id a v té druhé email..

$grid = $this->create($name);
        //$grid->setDataRepository($this->repository->getPricelists()->fetchAll());

        $clientId = $this->presenter->getParameter('id');
        if ($clientId) {
            // $client = $this->clientRepository->getById($clientId);
            $grid->setFilter(['user_id' => $clientId ?: "error"]);
        }

        $grid->addColumnNumber('user_id', 'User ID')
            ->setFilterText()
            ->setExactSearch();
        //->setTemplate(__DIR__ . '/username.latte');

        /*$grid->unsetFilter('user_id')
            ->getColumn('user_id')
            ->setFilterText('user_id.email');*/

        $grid->addColumnDateTime('time');
        $grid->addColumnText('file_name', 'URL');
        $grid->addColumnText('export_type', 'Typ');
        $grid->addActionCallback('download', 'Stáhnout', function ($id) {
            try {
                $file = $this->repository->getById($id)->file_name;
                $file = explode('/', $file);
                $file = array_pop($file);
                $this->getPresenter()->terminate((new FileResponse(WWW_DIR . '/data/pricelists/' . $file, $file))
                    ->send($this->getPresenter()->getHttpRequest(), $this->getPresenter()->getHttpResponse()));
            } catch (BadRequestException $e) {
                $this->getPresenter()->flashMessage($e->getMessage());
            }
        });
Pavel Janda
Člen | 977
+
0
-

@magenzajin Nezdá se mi, že by tato factory vyhazovala There is already action at key [email] defined… nemáš tam žádnou akci na klíči email.

magenzajin
Člen | 9
+
0
-

To je původní třída. Když do ní zkusím dle tvého příspěvku s datasource <?php $grid->setDataSource($this->context->table(‚client‘)); $grid->addColumnText(‚email‘, ‚Email‘, ‚client‘); ?>, tak se pak ohlásí There is already action at key [email] defined..
takhle tam vypadají ještě uses:

<?php
namespace ***\Components;

use app\components\Grids\BaseGridControl;
use Nette\Application\BadRequestException;
use Nette\Application\Responses\FileResponse;
use *****\Permission;
use *****\PricelistsHistoryRepository;

class PricelistGridControl extends BaseGridControl
{
...
?>
Pavel Janda
Člen | 977
+
0
-

@magenzajin Zdá se mi, že další diskuze už nepatří do tohoto vlákna..

Zkus postupovat fakt postupně a co nejjednodušeji. Udělej si prázdnou factory, kam dáš to, co jsem poslal. Můj kód jistě danou výjimku nevyhodí. A pak postupně přidávej řádek po řádku další funkcionalitu. Myslím, že tak najdeš problém, který ti výjimku způsobuje.

Píšeš, že dědíš od nějakého BaseGridControl → nedefinuje se ti třeba tam už nějaká akce nebo nějaký sloupec?

Atd.

magenzajin
Člen | 9
+
+1
-

Už na tom dělám. Celá ta implementace gridu u nás je nějak mimo .. Každopádně díky. :)

zoool
Člen | 89
+
0
-

Ahoj dají se nějak získat filtrované data z datagridu? Zkoušel jsem to nějak vytáhnout pří zavolání onRender, ale nějak se mi to nedaří. Chtěl bych je použít pro vykreslení grafu. Děkuji

Editoval zoool (23. 6. 2019 15:46)

jikki
Člen | 73
+
0
-

Ahoj lidi,
jak byste udělali tabulku, která bude mít možnost přepnout zobrazení položek jednotlivě (zobrazí se každý položka databáze) nebo seskupeně (položky se stejnými vlastnosti a jejích počet)?

Zatím jsem to vyrešil následovně:
Přidal jsem dvě tlačítka do toolbaru, ‚zobrazit jednotlivě‘ a ‚zobrazit seskupeně‘. Handly těch dvou tlačítek mění ajaxovým požadavkem hodnotu v session podle toho zda chci zobrazit jednotlivě nebo seskupeně a udělá reload tabulky. Podle hodnoty v session také nastavuji v metodě createComponentMyGrid dataSource a zobrazuji sloupce. Pro pohled seskupeně přidávám do dotazu Count(*) a GroupBy a vynechávám některé sloupce, které mají jedinečné hodnoty.

Tohle řešení funguje, ale jen do dody než použiju filtry. Pokud začnu používat filtry, tak přepnutí nefunguje na první kliknutí, ale až na druhé. Nedaří se mi to vyřešit, aby to fungovalo i s při použití filtrů, tak jak se očekává. Jedinné řešení je používat redirect(‚this‘) místo ajaxu + reloadu tabulky. Nicméně rád bych to zprovoznil s ajaxem.

Poradí někdo lepší způsob? Případně pokud bych udělat sandbox na githubu?

Díky za rady

Pavel Janda
Člen | 977
+
0
-

@zool Třída Ublaboo\DataGrid\DataModel (neřešil bych její jméno, historické důvody…) má eventy ::$onBeforeFilter, ::$onAfterFilter a ::$onAfterPaginated. Ty by mohly fungovat pro tvůj účel skvěle. Akorát se bohužel nedostaneš k instanci toho dataModelu. Nicméně pokud bys do masteru poslal pull-request s přidáním metody ::getDataModel(): DataModel do třídy DataGrid, tak ho rád mergnu. 👍

jikki
Člen | 73
+
0
-

Ahoj,

k čemu slouží signál refreshState?

$grid->setRefreshUrl(false);

Myslel jsem, že slouží pro URL refresh, ale mám to zákázané a signál se stále volá. Jak to vypnout? Zkoušel jsem to i v demu a chová se to stejně.

Díky

Petr Parolek
Člen | 455
+
0
-

Pavel Janda napsal(a):

@IJVo Nezmizela. :) Jen se přejmenovala kvůli PHP 7.2 a dědičnosti. A když už jsem dělal BC break, udělal jsem ho pořádně:

$grid->setConfirm('Do you really want to delete item %d?', 'id');

->

$grid->setConfirmation(new StringConfirmation('Do you really want to delete item %d?', 'id'));

A pro callback confirmation je tam CallbackConfirmation.

Jakmile vydám verzi 6, pustím sem celé release notes. Už je to za dveřmi!!

Ahoj, chybí v dokumentaci – stále je tam ->setConfirm('Do you really want to delete row %s?', 'name'); // Second parameter is optional https://github.com/…s/actions.md#…, mám poslat PR?

Pavel Janda
Člen | 977
+
0
-

@ppar Ano, prosím. :)

dTTb
Člen | 30
+
0
-

Nevim jestli me nepostihl zachvat slepoty, ale nemuzu ve full dokumentaci najit filtry (krom odstavce v kapitole Localization). Na puvodnich strankach je jim venovana cela kapitola. Nebo je ublaboo.org hlavni zdroj dokumentace?

Pavel Janda
Člen | 977
+
0
-

@dTTb Jojo, ta stránka tam chybí, víme o tom, podíváme se na to.

Jako hlavní zdroj dokumentace by měly sloužit README na GitHubu (https://github.com/…master/.docs), které se generují do čitelnější formy na stránkách Contributte. 👍

Felix
Nette Core | 1197
+
+1
-

@dTTb @PavelJanda Fixed. https://contributte.org/…filters.html

Pavel Janda
Člen | 977
+
0
-

@Felix It still can not be seen in the sidebar navigation …

magenzajin
Člen | 9
+
0
-

Ahoj,
už jsem tu něco podobného řešil. Jak řešíte ( co nejelegantněji :) ) více datasourců v jednom gridu? Díkes

dTTb
Člen | 30
+
0
-

@Felix diky

Jeste drobny dotaz ke Column Link. Da se nejak jednoduse zmenit text odkazu ktery to generuje? Pridat callback, parsovat vygenerovanej odkaz a zase odkaz lepit mi neprislo jako dobrej napad. Nakonec jsem si podedil DataGrid a ColumnLink, ale ani to mi neprijde idealni.

RePRO
Člen | 32
+
0
-

Ahoj. Mám problém s řazením a poté filtrem.

Mám dvě pole datum a osoba, jenže když si pole datum seřadím vzestupně a dám poté filtr osoby, tak se mi data seřadí do výchozího stavu (default sort). Avšak zobáček řazení zůstane OK :D Potřebuji nechat datum jak bylo. Je možné tohle nějak pořešit?

Failips
Člen | 54
+
0
-

Ahoj,

po upgrade na Ublaboo/Datagrid v6.2.0 som narazil na chybičku:

Call to undefined method Ublaboo\DataGrid\Column\Action::setConfirm()

kód je nasledovný:

$grid->addAction('delete', '', 'deleteKeyword!')
	->setIcon('trash')
	->setTitle('Smazat')
	->setClass('btn btn-xs btn-danger ajax')
	->setConfirm('Vážně si přejete odstranit klíčové slovo %s?','nazov');

Čím bola nahradená funkcia setConfirm() a aké je jej správne použitie?

Vďaka, Filip.

Failips
Člen | 54
+
0
-

radas napsal(a):

@Failips https://github.com/…s/tag/v6.0.0

Ďakujem. Presne preto sa pýtam na správne použitie (nejakú ukážku), nakoľko nemám ani potuchy čo za triedy sú StringConfirmation a CallbackConfirmation a ako sa s nimi pracuje pokiaľ chcem dosiahnuť rovnakých výsledkov ako v predchádzajúcich verziách.

Failips
Člen | 54
+
0
-

Ok. Tu je riešenie pre tých, ktorí by mali podobný problém :D Použitie tejto funkcie je fakt nádherné :D

$grid->addAction('delete', '', 'deleteKategoria!')
    ->setIcon('trash')
    ->setTitle('Smazat')
    ->setClass('btn btn-xs btn-danger ajax')
    ->setConfirmation(new \Ublaboo\DataGrid\Column\Action\Confirmation\StringConfirmation('Vážně si přejete odstranit kategorii %s?','nazov'));

Editoval Failips (16. 7. 2019 11:50)

Pavel Janda
Člen | 977
+
0
-

@Failips Nádherné myslíš ironicky? :) Udělal jsem to tak se kvůli zachování typovosti. Chápu, že se to může zdád na první pohled nepřehledné, mně to ale připadá ve výsledku přehlednější. :P

Failips
Člen | 54
+
0
-

Narazil som na ďalší problém, s ktorým si dosť lámem hlavu. Rád by som použil funkciu setItemsDetail podobne ako je to ukázané v ukážkach .

Kód Presenter:

$grid->setItemsDetail(APP_DIR . '/MainModule/templates/Porada/grid_item_detail.latte');
$grid->setItemsDetailForm(function(\Nette\Forms\Container $container) use ($grid, $presenter) {
	$container->addHidden('id');
	$container->addText('nazov');

	$container->addSubmit('save', 'Save')
		->onClick[] = function($button) use ($grid, $presenter) {
        	$values = $button->getParent()->getValues();

			$presenter['examplesGrid']->redrawItem($values->id);
		};
});

Kód Latte:

{extends $originalTemplate}

{block detail}
	<h2>{$item->getNazov()}</h2>

	<p>Lorem ipsum ...</p>

	{formContainer items_detail_form-{$item->getId()} }
		{input id, value => $item->getId()}
		{input nazov, value => $item->getNazov()}
		{input save}
	{/formContainer}
{/block}

Chyba vyvolaná riadkom „{formContainer items_detail_form-{$item->getId()} }“:

Nette\InvalidArgumentException

Component with name '1019' does not exist.

Ak daný riadok upravíme na {formContainer items_detail_form} }, tak sa cez chybu dostaneme ale dostaneme ďalšiu vyvolanú riadkom „{input id, value ⇒ $item->getId()}“:

Nette\MemberAccessException

Call to undefined method Nette\Forms\Container::getControl(), did you mean getControls()

A pokiaľ v tomto stave máme v detaile (vo vnútri formContainer items_detail_form) ďalší formContainer (napr. inner_form), tak $container v presentéri nebude odkazovať na items_detail_form ale na tento ďalší formContainer, čiže ak budeme chcieť vložiť do detailu niečo napr. pomocou funkcie addHidden(), tak sa tento prvok vloží do toho inner_form a
nie do items_detail_form.

Je chyba v Ublaboo/Datagrid alebo je to spôsobené mojou zlou implementáciou ItemsDetail? Ak je chyba na mojej strane ako sa má správne implementovať ItemsDetail vo Ublaboo/Datagrid v6.2.0?

Ďakujem, Filip.

Failips
Člen | 54
+
0
-

Pavel Janda napsal(a):

@Failips Nádherné myslíš ironicky? :) Udělal jsem to tak se kvůli zachování typovosti. Chápu, že se to může zdád na první pohled nepřehledné, mně to ale připadá ve výsledku přehlednější. :P

Áno ironicky ale iba si na to musím zvyknúť :)

Failips
Člen | 54
+
0
-

Nefunguje mi inlineAdd v Ublaboo/Datagrid v6.2.0. Máte s tým skúsenosti?

Díky, Filip

Pavel Janda
Člen | 977
+
0
-

Demo (viz zde) funguje z repozitáře v playgroundu – https://github.com/…tte-datagrid. Zkus to u sebe rozjet a porovnat se svým kódem. :)

Failips
Člen | 54
+
0
-

Díky za tip, rozbehol som to u seba. Aby som si bol istý, že je CSS a JS rovnaké tak som do playground verzie vložil môj bower.json avšak, nechápem prečo, inlineAdd v playground ide a u mňa s rovankým kódom nejde :D Nejaké tipy, čo by som ešte mohol skontrolovať?? :D

Edit: všimol som si, že riadok pre inlineAdd sa pridá avšak je skrytý.

Editoval Failips (23. 7. 2019 12:37)

magenzajin
Člen | 9
+
0
-

Ahoj,
jako modalEdit, který mi dá formulář editace např.klienta se vším, co chci editovat.. rád bych duplikoval klienta, se stejným formulářem, ale abych neupdatoval, ale nově insertoval… Je nějaká spešl feature datagridu pro toto??
Dík

R@da
Člen | 28
+
0
-

Ahoj,
už se to tu řešilo, ale bohužel jsem nikde nenašel odpověď. Řeším, jak při inline editaci zobrazit datepicker?
Respektive, zobrazit se mi ho podařilo, ale když zvolím datum, tak se textbox zruší a nic se neuloží.
Mám to nyní takto:

$grid->addColumnDateTime('customer_invoice_paid', 'Zaplaceno')
            ->setEditableCallback(function($id, $value) {
                echo("Id: $id, new value: $value"); die;
            })
            ->setEditableInputType('text', ['class' => 'datepicker', 'onClick' => '$(this).datepicker("show");']);

Do budoucna by bylo možná dobré automaticky nabízet kalendář, když se jedná o „ColumnDateTime“. To jenom takový nápad na vylepšení.
Má někdo stejný problém? Jak to prosím vyřešit?

Předem moc děkuju.

Failips
Člen | 54
+
0
-

Failips napsal(a):

Díky za tip, rozbehol som to u seba. Aby som si bol istý, že je CSS a JS rovnaké tak som do playground verzie vložil môj bower.json avšak, nechápem prečo, inlineAdd v playground ide a u mňa s rovankým kódom nejde :D Nejaké tipy, čo by som ešte mohol skontrolovať?? :D

Edit: všimol som si, že riadok pre inlineAdd sa pridá avšak je skrytý.

Po hlbšom skúmaní kódu som zistil, že pri kliku na tlačítko „+“, ktoré má zobraziť riadok s inlineAdd, sa nezavolá event, ktorý má za úlohu odstrániť z vytvoreného riadku inlineAdd triedu datagrid-row-inline-add-hidden (datagrid.js):

$(document).on('click', '[data-datagrid-toggle-inline-add]', function(e) {
  var row;
  e.stopPropagation();
  e.preventDefault();
  row = $(this).closest('.datagrid').find('.datagrid-row-inline-add');
  if (row.hasClass('datagrid-row-inline-add-hidden')) {
    row.removeClass('datagrid-row-inline-add-hidden');
  }
  return row.find('input:not([readonly]),textarea:not([readonly])').first().focus();
});

Považujete toto za správne chovanie a je daná trieda odstraňovaná iným spôsobom (ktorý u mňa nefunguje)?

Failips
Člen | 54
+
0
-

Existuje spôsob, ktorým by sa pri vykreslení inlineEditu dal zachytiť event v jQuery/JS?

zoool
Člen | 89
+
0
-

Ahoj narazil jsem na problém v Datagridu ^6.2, setConfirm u akce se přejmenovalo na setConfirmation s použitím správného Confirmation? V dokumentaci je to pořád stejné.
Děkuji

R@da
Člen | 28
+
+1
-

zoool napsal(a):

Ahoj narazil jsem na problém v Datagridu ^6.2, setConfirm u akce se přejmenovalo na setConfirmation s použitím správného Confirmation? V dokumentaci je to pořád stejné.
Děkuji

Ahoj,
já to vyřešil takto:

use Ublaboo\DataGrid\Column\Action\Confirmation\StringConfirmation;

$grid->addAction('storno', '', 'storno!')
            ->setIcon('times')
            ->setTitle('Storno')
            ->setClass('btn btn-xs btn-danger ajax')
            ->setConfirmation(new StringConfirmation("Opravdu chcete stornovat?"));
Pavel Janda
Člen | 977
+
0
-

@zoool Ahoj, opravil jsem dokumentaci: https://contributte.org/…actions.html#api

Jinak pro všechny: kdyby někdy někdo narazil na bug v dokumentaci, lze poslat opravný PR: https://github.com/…master/.docs :) :) 👍👻

Pavel Janda
Člen | 977
+
0
-

Failips napsal(a):

Existuje spôsob, ktorým by sa pri vykreslení inlineEditu dal zachytiť event v jQuery/JS?

Určitě ano. V JS datagridu je následující kód:

$.nette.ext('datagrid.inline-editing', {
	success: function(payload) {
		if (payload._datagrid_inline_editing) {
			// Něco...
		}
	}
});

Klidně si můžeš zaregistrovat vlastní nette.ajax.js extension, kde bude místo „// Něco…“ tvůj kód.

nocturne32
Člen | 21
+
+1
-

Ahoj, jak je to s dokumentací datagridu na ublaboo? Pouze to přesměrovává na contributte, ale tam toho moc není, co se informací týče.

Edit: ah, pardon, akorát teď jsem si všiml, že v repu jsou alespoň ty docs více rozepsaný, ale škoda té stránky, byla moc fajn :-)

Editoval nocturne32 (30. 7. 2019 12:13)

cafesk8
Člen | 103
+
0
-

Zdravím,

mám export do CSV

$grid->addExportCsv('Export', 'users'.time().'.csv')
	->setTitle('Export uživatelů')
	->setColumns([
		$column_email,
		...
		...
	]);

ale klient požaduje aby export byl v XLS, protože pracují s MS Excel a v něm se prý po otevření CSV a opětovném uložení se z něj stane sypaný čaj a všechna data na řádku již nejsou ve sloupcích, ale za sebou na řádku. Dále má problém s diakritikou, která se mu nezobrazí správně (mně ano, stejně tak v Libre Office, tak v Google Sheets).

Máte nějaký nápad jak udělat export do XLS? Nedá se třeba soubor místo stažení prohlížečem pouze někde uložit a pak si ho převést pomocí phpoffice/phpspreadsheet?

Děkuji

Felix
Nette Core | 1197
+
0
-

nocturne32 napsal(a):

Ahoj, jak je to s dokumentací datagridu na ublaboo? Pouze to přesměrovává na contributte, ale tam toho moc není, co se informací týče.

Edit: ah, pardon, akorát teď jsem si všiml, že v repu jsou alespoň ty docs více rozepsaný, ale škoda té stránky, byla moc fajn :-)

Ta stranka se premistila na jiny web, jinak obsah zustal stejny nebo lepsi. :-)