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

sibka
Člen | 24
+
0
-

@PavelJanda Ano, aby třeba podle nějaké hodnoty u záznamu v řádku se některé možnosti ze selectu vynechaly.

Pavel Janda
Člen | 977
+
0
-

@sibka

Nová malá verze – v3.1.0

Přidal jsem $column_callbacks. To je pidivěc, která dovolí šáhnout na sloupce těsně před vyrenderováním položek. Ukázka:

$grid->addColumnLink('link', 'Link', 'this#demo', 'name', ['id', 'surname' => 'name']);

$grid->addColumnStatus('status', 'Status')
	->addOption(1, 'Online')
		->setClass('btn-success')
		->endOption()
	->addOption(2, 'Standby')
		->setClass('btn-primary')
		->endOption()
	->addOption(0, 'Offline')
		->setClass('btn-danger')
		->endOption()
	->onChange[] = [$this, 'changeStatus'];

$grid->addColumnCallback('status', function($column, $item) {
	if ($item->id == 2) {
		$column->removeOption(2);
	}
});

$grid->addColumnCallback('link', function($column, $item) {
	if ($item->id == 2) {
		$column->setRenderer(function() {
			return '';
		});
	}
});

Tento příklad odebere option s hodnotou 2 pro položku s id == 2. Pro stejnou položku bude chybět sloupec s odkazem.

Lze manipulovat se všemi sloupci..

Dokumentace zde.

Editoval Pavel Janda (24. 3. 2016 10:28)

pitr82
Člen | 121
+
0
-

@PavelJanda Ahoj, jedu na masteru a přestalo mi fungovat potvrzování u akcí :

$grid->addAction('disable', '', 'disable!')
		->setIcon('lock')
		->setTitle("sdsdsd")
		->setClass('btn btn-xs btn-warning ajax')
		->setConfirm("Opravdu chcete odstranit");

Do html vygeneruje data-datagrid-confirm ale javascript se nezavolá

$grid->addAction('enable', '', 'enable!')
		->setIcon('unlock')
		->setTitle($this->translator->translate('admin.userGrid.enable'))
		->setClass('btn btn-xs btn-success ajax')
		->setConfirm(function($item) {
		    return "Id: $item->id - Opravdu odstaranit?";

Tak mi skončí chybou:** Illegal offset type in isset or empty **
/datagrid/src/Localization/SimpleTranslator.php:60

Změnilo se něco ?

Pavel Janda
Člen | 977
+
0
-

@pitr82 Omlouvám se, zapomněl jsem return..

Přesně proto strávím víkend nad psaním testů.

Editoval Pavel Janda (24. 3. 2016 12:32)

pitr82
Člen | 121
+
0
-

Pavel Janda napsal(a):

@pitr82 Omlouvám se, zapomněl jsem return..

Přesně proto strávím víkend nad psaním testů.

Prosímtě, nezmizel „data-datagrid-confirm“ z javasriptu ?
Neprovede se mi vyskakovací okno… aktualizoval jsem bover a vybral jsem verzi nette-forms 2.3.0

nette-forms#>= 2.3.0 which resolved to 2.3.8 and is required by ublaboo-datagrid#2.3.11
Pavel Janda
Člen | 977
+
0
-

@pitr82 Tohle je poslední verze: https://github.com/…/datagrid.js#…

jurajvt
Člen | 18
+
0
-

Ak agregujem dáta z cudzej tabuľky, paginator dostane nesprávne výsledky.

$orders = $this->arrived->findAll()
    ->select('SUM(arrived.weight) AS weight_sum')
    ->select('order.id, order.code AS order_code, order.amount AS order_amount')
    ->group('order_id');

Výsledkom sú dva dotazy:

SELECT COUNT(arrived.id)
FROM arrived

SELECT SUM(weight) AS weight_sum, order.id, order.code AS order_code, order.amount
AS order_amount
FROM arrived
LEFT JOIN order ON arrived.order_id = order.id
GROUP BY order_id

Správne by sa mali počítať výsledky po agregácii.

V Grido sa to dá vyriešiť takto:

$grid->model->callback['getCount'] = function() use ($orders) {
    return $orders->count();
};

Ako to riešiť v tomto Datagrid-e?

Inak, Pavel – veľmi dobrá práca. Ďakujem.

Editoval jurajvt (26. 3. 2016 23:28)

CZechBoY
Člen | 3608
+
0
-

V tom Grido to je celkem hnusny reseni…
Jaky je spravny sql dotaz na pocitani a co vlastne vypisujes? Neslo by vybirat z tabulky order?

jurajvt
Člen | 18
+
0
-

Samozrejme, máš pravdu. Stačilo to otočiť (vyberať z order). Ďakujem!

Dark0ne
Člen | 47
+
0
-

Ahoj,
měl bych další dotaz. Řeším teď responzivnost webu a bohužel mi datagrid trochu utíká z contentu. Chtěl jsem se zeptat, zda jsem něco v dokumentaci přehlédnul, nebo zda bys mi neporadil, kde změnit styly, aby se celá tabulka přizpůsobila (potřebuji do 320 px).
Díky

pitr82
Člen | 121
+
0
-

Ahoj,
u statusu, když ho nechci odeslat ajaxově, nastavím

->setClass('btn-primary', 'btn btn-default btn-xs')

tak se mi zruší ajax u třídy button, ale ne u a
pořád se to odesílá ajaxově

<div class="dropdown">
		<button class="dropdown-toggle btn-danger btn btn-xs" type="button" data-toggle="dropdown">

			Neaktuální 		</button>
	<ul class="dropdown-menu">
		<li>
			<a **class="ajax"** href="#">
				Aktuální
			</a>
		</li>
		<li>
			<a **class="ajax"** href="#">
				Neaktuální
			</a>
		</li>
	</ul>
</div>
Pavel Janda
Člen | 977
+
0
-

@Dark0ne Doporučuji si vytvořit vlastní template datagridu. Nebo jen upravit. Já, pokud potřebuji responzivní administraci například, vytvořím si vlastní template, kde vůbec nefiguruje element <table>.

Pavel Janda
Člen | 977
+
0
-

@pitr82 Mrknu, dávám do issue.

Dark0ne
Člen | 47
+
0
-

@PavelJanda Díky za radu. Ještě jsem se chtěl zeptat, najednou mi začal blbnout filtr na datum. Stává se to, že když kliknu pro výběr konkrétního data z kalendáře, tak asi za sekundu se refreshne stránka a ten výběr zmizí a člověk tam musí najet znovu. Netušíš, čím by to mohlo být?

Editoval Dark0ne (2. 4. 2016 12:59)

Pavel Janda
Člen | 977
+
0
-

@Dark0ne To nevím. Na webu se to neděje. A nemělo by – sám datagrid překresluje při filtrování pouze vypisovaná data (+ stránkování) a nikoliv filtry. Právě proto, aby zůstal focus na inputech filtrů. Nepřekresluješ někde celý control manuálně?

Pavel Kouřil
Člen | 128
+
0
-

Pavel Janda napsal(a):

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

Konečně jsem se vrátil k projektu kde datagrid používám, a chci se vrátit k tomuto :)

Nešlo by ty filtry mít nějak taky na to přetížení vlastní šablonou? Např. předefinování bloku {filterDateRange}; a nebo nastavování templatu filtru v gridu, a možnost konfigurace gridu s vlastními defaultními templates filtrů.

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

Když nejdříve filtruji a pak řadím, přijdu o filtr. I v demu. To je feature? :)

Pavel Janda
Člen | 977
+
0
-

@PavelKouřil DataGridí filtry mohou mít vlastní šablonu. Co se týče definice šablon filtrů pomocí bloků, přidávám to do issues na githubu, taky se mi to líbí.

Pavel Janda
Člen | 977
+
+1
-

@PavelKravčík Heh, díky. To je tím, že se nepřerenderovávají ajaxově ty sortící odkazy. Ale po druhém a dalším kliknutí už to zas jede. :D Fixnu o víkendu.

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

@PavelJanda: V pohodě díky, já už jim to vysvětlil jako feature, že si mají nejdřív řadit a pak až filtrovat a neotravovat programátory. :D

Pavel Janda
Člen | 977
+
0
-

@PavelKravčík :D Ježiš. Tak to opravím ještě dneska večer.

Editoval Pavel Janda (8. 4. 2016 15:04)

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

@PavelJanda: Nadsázka. :) Ví o tom, jak to dočasně obejít, sám se na to chtěl podívat hlouběji v neděli, pokud by to byla feature. Takže určitě se běž někam bavit radši večer.

Pavel Janda
Člen | 977
+
+1
-

@PavelKravčík v3.1.4

Pavel Janda
Člen | 977
+
0
-

@pitr82 v3.1.5 Docílíš toho metodou Status\Option::setClassInDropDown('' /* Nebo tvoje jina trida */):

$status->addOption(1, 'Online')
	->setClassInDropDown(NULL); // By default 'ajax'
Petr Steinbauer
Člen | 26
+
0
-

Zdravím, je možné v doplňkové šabloně `$grid->setTemplateFile(__DIR__ . '/templates/Datagrid/user.latte');` zavolat/vytvořit formulář?
Tedy cca toto:

{extends $original_template}
{block detail}
	{control userDescription}
{/block}

Zkoušel jsem createComponentUserDescription narvat všude možně, dokonce i do BasePresenter.php ale nedaří se.

Je vůbec možno zde použít formulář? A pokud ano, jak?

Pavel Janda
Člen | 977
+
0
-

@PetrSteinbauer To jistě takto nelze – formulář je vytvářen nad rodičovskou komponentou, tedy aktuálně DataGridem. Momentálně je nejjednodušší podědit si DataGrid, kde si vytvoříš továrničku formuláře.

Pokud vymyslíš nějaký podnětný příklad a ještě někdo se připojí s prosbou o implementaci nějakého dynamického řešení, založ issue na takovou feature.

Editoval Pavel Janda (11. 4. 2016 15:28)

Petr Steinbauer
Člen | 26
+
+2
-

@PavelJanda
pokusím se to sepsat ještě jednou sem jako před-schválení:

Využívám vestavěnou ublaboo šablonu (oko) jako náhled na uživatele – takový letecký panel.
Zobrazuji stav objednávek, a další stavy. Nově si zadavatel vymyslel, že by rád přidával body přímo odsud a rovněž by si rád měnil stavy objednávek odsud a také by rád připisoval poznámku k uživatelu.
Vše v této části a přijde mi to i logické. Takto to vypadá vizuálně:
image

Bohužel to však nepůjde, v implementované šabloně nemohu použít nic z tohoto:
<a n:href="Eshop:vyrobek"></a>
{Strings::webalize($item->title)}
<form n:name>
{control jmenoFormulare}
<a n:href="signal!"></a>

Předpokládám, že toto využití náhledu (jako „leteckého panelu“) by jistě využilo více lidí. Co vy na to?

Pavel Janda
Člen | 977
+
+1
-

@PetrSteinbauer Tak pojďme to probrat bod po bodu:

  1. Makro n:href nelze používat, protože v komponentě se odkazuješ právě na tu komponentu. Musíš použít makro plink, pokud chceš odkázat na presenter. To platí pro celé Nette a všechny komponenty, najdeš to v dokumentaci Nette.
  2. Chybí ti tam namespace, hádám: {Nette\Utils\Strings::webalize($item->title)}
  3. To už jsem psal v bodě 1

Je pravda, že bych mohl nějak udělat dynamické načítání component ještě v datagridu. Zapřemýšlím nad tím. Do té doby (jak jsem už psal) si můžeš jednoduše podědit DataGrid a v tvé třídě (class MyGrid extends Ublaboo\DataGrid\DataGrid) si vytvoříš továrnu potřebného formuláře. Pravděpodobně budeš časem chtít použít i Nette\Application\UI\Multiplier, k tomu třeba ještě napíšu nějakou ukázku.

Super, tohle hoď do issue, akorát odeber ty odkazy a použití statické metody Strings::webalize.. :)

Editoval Pavel Janda (11. 4. 2016 21:12)

Petr Steinbauer
Člen | 26
+
0
-

@PavelJanda děkuji.
Potvrzuji, že body 1 a 2 jsou tak jak říkáš.
Dědění Datagridu: snad to zvládnu, návod je dost podrobný.
Issue jsem upravil pravopisně a odeslal.

Děkuji.

exquis
Člen | 82
+
0
-

Tušíte proč by mi mohl datagrid při exportu do CSV vyhazovat chybu:

Component '' is not attached to 'Nette\Application\UI\Presenter'

Kod:

function createComponentVyhledavaniNaWebu()
{
    $Grid = new DataGrid();

    $Grid->setDataSource($this->Searching->getTblSearching()->getAll());
    $Grid->setItemsPerPageList($this->itemsPerPage);
    $Grid->setDefaultSort(array("date" => "DESC"));


    $Grid->addColumnDateTime("date", "Datum")->setSortable();
    $Grid->addColumnText("term", "Pojem")->setSortable()->setFilterText();
    $Grid->addColumnText("url", "Na URL")->setSortable()->setFilterText();
    $Grid->addColumnText("ip", "Počet hledání")->setSortable()->setFilterText();

    $Grid->addExportCsv('EXPORT', 'examples.csv');

    return $Grid;

}
Pavel Kravčík
Člen | 1180
+
+1
-

@exquis:

function createComponentVyhledavaniNaWebu($name)
{
    $Grid = new DataGrid($this, $name);

Předpokládám, že na poslání souboru CSV je potřeba response a ta je navázána na presenter.

Pavel Janda
Člen | 977
+
0
-

Stejnak je to divné. Mrknu.

Petr Steinbauer
Člen | 26
+
0
-

@exquis : pěkná náhoda:
teď jsem viděl zmíněnou chybu: Component '' is not attached – měl jsem 2× jsAjax pracování za sebou (v base a presentu) – jedno jsem vyřadil a vyřešeno. Asi to nebude to samé, že ne?

exquis
Člen | 82
+
0
-

Petr Steinbauer napsal(a):

@exquis : pěkná náhoda:
teď jsem viděl zmíněnou chybu: Component '' is not attached – měl jsem 2× jsAjax pracování za sebou (v base a presentu) – jedno jsem vyřadil a vyřešeno. Asi to nebude to samé, že ne?

bohužel, u mně je spouštěč přidání „$Grid->addExportCsv(‚EXPORT‘, ‚examples.csv‘);“ do kódu, dokud to tam není, tak vše běhá bez problému. Chybu vyhazoval už na verzích okolo 2.1.(nevím přesně), kdy byl export již zabudován, ale myslel jsem, že je to někde má chyba, tak jsem to neřešil s tím, že to zkusím později.

Bohužel ani později se to nepovedlo.

exquis
Člen | 82
+
+1
-

Když to udělám jak píše @PavelKravčík tak to běhá

function createComponentVyhledavaniNaWebu($name)
{
    $Grid = new DataGrid($this, $name);
pitr82
Člen | 121
+
0
-

Pavel Janda napsal(a):

@PetrSteinbauer Tak pojďme to probrat bod po bodu:

  1. Makro n:href nelze používat, protože v komponentě se odkazuješ právě na tu komponentu. Musíš použít makro plink, pokud chceš odkázat na presenter. To platí pro celé Nette a všechny komponenty, najdeš to v dokumentaci Nette.
  2. Chybí ti tam namespace, hádám: {Nette\Utils\Strings::webalize($item->title)}
  3. To už jsem psal v bodě 1

Je pravda, že bych mohl nějak udělat dynamické načítání component ještě v datagridu. Zapřemýšlím nad tím. Do té doby (jak jsem už psal) si můžeš jednoduše podědit DataGrid a v tvé třídě (class MyGrid extends Ublaboo\DataGrid\DataGrid) si vytvoříš továrnu potřebného formuláře. Pravděpodobně budeš časem chtít použít i Nette\Application\UI\Multiplier, k tomu třeba ještě napíšu nějakou ukázku.

Super, tohle hoď do issue, akorát odeber ty odkazy a použití statické metody Strings::webalize.. :)

Taky bych se přikláněl nějaké ukázce… Díky

CZechBoY
Člen | 3608
+
0
-

Tak jsem taky podlehl a konečně zkouším tento datagrid ;-)

Zkouším tu mini editaci a chtěl bych si dát místo textarea obyčejnej input[type=text]. Dokumentace se zmiňuje o

	->setEditableInputType('text', ['class' => 'form-control']);

jenže žádnou takovou metodu mi php nenajde :(
Call to undefined method Ublaboo\DataGrid\Column\ColumnText::setEditableInputType().

Pavel Janda
Člen | 977
+
0
-

@CZechBoY Zatím je to v masteru, během pár dní (možná dnes) vyjde v3.2. V té to bude otagované.

tatyalien
Člen | 239
+
0
-

Ahoj,
mám dotaz, v projektech používám Dibi, ale nepoužívám fluent a DibiRow. Sql si poskládám a vracím entity:

	function getExampleData(){
		$sql = '....';
		$resource = $this->connection->query($sql);
		$resource->setRowFactory(array($this, 'getRow'));
		$data = $resource->fetchAll();
		$resource->free();
		return $data;
	}

	public function getRow($data)
	{
		$entity = new ExampleEntity();
		$entity->hydrate($data);
		return $entity;
	}

ExampleEntity:

class ExampleEntity
{

	private $id;

	private $user;

	//getter / setter
}

Jde to nějak napojit na datagrit? Nechtěl bych zbytečně data předávat do pole…

Pavel Janda
Člen | 977
+
0
-

@tatyalien Stačí si napsat vlastní datasource, který bude implementovat Ublaboo\DataGrid\DataSource\IDataSource (sortění, filtrování, limitění apod, klasika).

Pokud s tím máš velký problém, můžeš dát někde na github svůj (kompletnější) způsob získávání dat a já se pokusím nastínit implementaci datasourcu.

Editoval Pavel Janda (17. 4. 2016 22:04)

Pavel Janda
Člen | 977
+
+2
-

Nová verze – v3.2.0

Díky všem za nápady a spolupráci!

Editoval Pavel Janda (17. 4. 2016 22:32)

tatyalien
Člen | 239
+
0
-

@PavelJanda hodil jsem hodně osekanou ukázku na bitbucket
Díky za ukázku :)

Pavel Janda
Člen | 977
+
+2
-

Nová verze – v3.3.0

David Grudl
Nette Core | 8108
+
+1
-

Narazil jsem na drobnost. Když filtru nastavím hodnotu:

$grid->addColumnText('status', 'Stav')
	->setFilterSelect([...])
	->setValue('value');

tak se sice zohlední při filtrování, ale ne při vykreslení selectboxu.

Btw, filtrování přes multiselect by bylo taky fajn.

Pavel Janda
Člen | 977
+
0
-

@DavidGrudl Metoda Filter::setValue() je určena spíš pro interní účely.. V momentě, kdy uživatel vyplní filtr v prohlížeči, DataGrid řekne filtru, že má nastavenou hodnotu (::setValue()) a data source si pak o tuto hodnotu řekne ($filter->isValueSet(), $filter->getCondition()).

Píšu si issue – nastavení defaultních hodnot filtru.

Nějaké nápady na ověřenou JS knihovnu, která zpříjemní práci s multiselectem?

Editoval Pavel Janda (19. 4. 2016 9:20)

Pavel Kouřil
Člen | 128
+
0
-

Pavel Janda napsal(a):

Nová verze – v3.2.0

Skvělé!

Ale pořád se nedají změnit např. všechny filtry typu daterange, že? Řídí se to podle parametru key v metodách jako addFilterDateRange(), pokud jsem dobře pochopil?

CZechBoY
Člen | 3608
+
+1
-

@PavelJanda Mně se celkem líbí https://silviomoreto.github.io/…ct/examples/ a neměl jsem s nim ani moc problémů :-)

Pavel Janda
Člen | 977
+
0
-

@PavelKouřil Ano, je to tak. Upřímně, do teď mi nedošlo, že by to mělo jít nastavit i takto globálně pro stejný TYP filtrů. Píšu si issue..

Pavel Janda
Člen | 977
+
0
-

@PavelKouřil Tak je to zatím v masteru. Dám to do další verze. Použití:

  1. Nastavíš šablonu, která extendí tu původní
  2. Každý filtr má svůj typ (Filter::getType()), jak se jmenuje si lze domyslet (text, select, …), nebo najít v property toho kterého filtru.
  3. Nadefinuješ blok typu filtru: {block filtertype-text}...{/block}, {block filtertype-select}...{/block}, …

Editoval Pavel Janda (19. 4. 2016 10:06)

chap
Člen | 81
+
+1
-

Super práce – radost sledovat vývoj. :)
Ten multiselect – jsem také pro silviomoreto/bootstrap-select