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

Pavel Janda
Člen | 977
+
+1
-

@romiix.org Strašně by se mi to tak líbilo. Už jsem nad tím přemýšlel, opravdu jedinou překážkou jsou nyní ty hromadné akce.

HTML5 form atributy – přesně tak, vyžadovalo by to nějaký IE-shit polyfill. Podpora: http://caniuse.com/#…

No, ještě bych měl asi chvilku počkat. :)

A nebo konečně založit nějakou beta větev.. Fajn.

Editoval Pavel Janda (5. 8. 2016 11:37)

Blujacker
Člen | 89
+
0
-

Ahoj,

narazil jsem na par veci:

  • hideable columns nefunguji s setRememberState(FALSE)
  • schovani / zobrazeni sloupce resetuje filtry
  • kdyz je pouzit outer filtr, tak se filtr zobrazuje i kdyz je sloupec schovan

Diky!

igor.pocta
Člen | 100
+
0
-

@PavelJanda
Ahoj, použití s Nextras, jak máš v dokumentaci, mi nefungovalo – neustále to házelo vyjímku Where expression has to be a string (Nextras\Dbal\InvalidArgumentException)

$grid->getFilter('name')
	->setCondition(function ($collection, $value) {
		$collection->getQueryBuilder()->andWhere(['name' => $value]);
	});

jsem zaměnil za

$grid->getFilter('name')
	->setCondition(function ($collection, $value) {
		$collection->getQueryBuilder()->andWhere('name LIKE %s', "%".$value."%");
	});

Zdroj: https://nextras.org/…uery-builder

a OK

Editoval igor.pocta (9. 8. 2016 8:27)

Pavel Janda
Člen | 977
+
0
-

@Blujacker 1, Ano, Datagrid::setRememberState(FALSE) sdělí datagridu, aby přestal pracovat se session, tudíž se nemá kam ukládat informace o skrytých sloupcích.

Jaké navrhuješ řešení? Vyhazovat nějakou notice, pokud chce uživatel skrývat sloupce bez session? Nebo zkusit vynutit jiné úložiště při zákazu použití session, třeba cache?

2, Jakou verzi používáš? Máš aktuální assety? Na webu dokumentace (ublaboo.org/datagrid) je vše v pořádku.

3, Hmm, toje otázka – schovat, neschovat? Přeci jde o filtr, ne o sloupec.

@igor.pocta Děkuji za report, opravím.

david.zlaty
Člen | 2
+
0
-

Zdravím,
zkouším datagrid, ale mám problem. Když použiju inline edit nebo inline add ajaxove krasne to funguje, bohuzel reload datagridu se provede, ale data aktualni tam nejsou az vždy po druhém reloadu ajaxu.

Setkal se někdo s chybou?

Ajax normalne funguje pri testovani. Assety jsou pres bower, všechno podle dokumentace.

Díky.

Pavel Janda
Člen | 977
+
0
-

@david.zlaty Ty používáš ArrayDataSource?

david.zlaty
Člen | 2
+
0
-

Ano přesně tak.

--- Upraveno
Ted jsem zkusil pouzit datagrid-nette-database-data-source a problem vyresen.
Ale zpusob predtim nejde.

Pavel Janda napsal(a):

@david.zlaty Ty používáš ArrayDataSource?

Editoval david.zlaty (10. 8. 2016 10:59)

Pavel Janda
Člen | 977
+
+2
-

@david.zlaty Vysvětlím, proč je tomu tak.

  1. V url je něco jako ?do=mujGrid-inlineEdit
  2. Nette chce vytvořit mujGrid, tak zavolá tvoji továrničku
  3. Tvoje továrnička vytvoří instanci datagridu, nastaví datasource, sloupce a filtry
  4. Tvoje továrnička vrátí datagrid
  5. Nette nad vrácenou komponentou zavolá ::handleInlineEdit, to asi zavolá nějaké tvoje callbacky
  6. Vykreslí se datagrid

Už je jasno? Datasource se nastavuje ještě před přidáním záznamu. Což je problém, pokud používáš ArrayDataSoure. Pokud bys používal cokoliv jiného, tak by se data tahaly „líně“ až při načítání dat.

Z principu to nelze řešit jinak. Takže:

  1. Bu'd si uděláš nějaký datasource, který bude „líně“ vracet data.
  2. Použiješ jiný datasource
  3. Třída InlineEdit má event ::$onCustomRedraw, do něj si přidej svůj callback. V něm můžeš znovu nastavit datasource (již aktuální) a udělat to, co by jinak udělal datagrid – překreslil změněný řádek: https://github.com/…DataGrid.php#…
  4. Nastav datasource znovu ještě jinak, například v eventu DataGrid::$onRender.
Barvoj
Člen | 60
+
0
-

Ahoj,

dneska se mi na projektu začala objevovat chyba „The variable ‚rows‘ already exists.“. Jedná se například o situaci, kdy chci pomocí „group action“ změnit stav některých řádků. Ajaxem se odešle požadavek na server a při jeho zpracování dojde k této chybě. Zdá se, že se na gridu volá 2× metoda render.

Nenarazil někdo z Vás na stejný problém?

Pavel Janda
Člen | 977
+
+1
-

@Barvoj Ano. Je to chyba v UI\Control. Buď pošli PR, kde bude místo $this->getTemplate()->add('rows', $rows); $this->getTemplate()->rows = $rows;, nebo si aktualizuj Nette na 2.4 :D (tuším, že už je to tam opraveno).

flamengo
Člen | 131
+
+1
-

Ahoj, tak jsem konečně nahodil tento DataGrid a je to paráda. Mám pár dotazů:

1/ Lze nastavit svoji šablonu paginatoru?
Zatím jsem přepsal tu ve složce vendor/, což asi nebude úplně správný přístup.

2/ Lze nastavit své vlastní šablony nějak globálně pro každé použití gridu, třeba přes config.neon případně jinak?

3/ Lze nějak nastavit CSS třídu buňce tabulky? Třeba nějak takto podobně:

$grid->addColumnNumber('number', 'Number')
	->setCssClass('width50');

Pokud si stránkuji, tak rozdílný počet znaků hodnot má ten neblahý efekt, že mi poskakuje šířka sloupečků. Dřív jsem to řešil právě nastavením třídy nějak takto <tr><td class="w25">. Měl jsem nadefinované CSS třídy pro různé šířky a tabulka potom neposkakovala.
Nebo to lze vyřešit jinak?
Každopádně možnost opatřit TD či TH svou vlastní CSS třídou by se mi hodila.

Předem díky za reakci.

Editoval flamengo (10. 8. 2016 20:39)

Pavel Janda
Člen | 977
+
0
-

@flamengo Ahoj.

  1. Ano, DataGrid::getPaginator()->setTemplateFile(...)
  2. Ano, ideálně si vytvoř třídu DataGridFactory, kterou si budeš předávat do presenterů/komponent, kde datagrid využíváš a tam místo new DataGrid budeš volat $this->datagridFactory->create($this, $name). Právě v této factory budeš dělat něco takového:
$grid = new DataGrid($this, $name);

$grid->setTemplateFile(...);

return $grid;
  1. Ano, viz dokumentace: http://ublaboo.org/datagrid/column#… :)
flamengo
Člen | 131
+
0
-

@PavelJanda Ahoj a díky moc. Bohužel nějaký problém:

Toto funguje v pohodě:

<?php
namespace Moje\DataGrid;
use Ublaboo\DataGrid\DataGrid;
interface IDataGridFactory
{
	/** @return DataGrid */
	function create();
}

Toto zobrazí chybu:

<?php
namespace Moje\DataGrid;
use Ublaboo\DataGrid\DataGrid;
interface IDataGridFactory
{
	/** @return DataGrid */
	function create($name){
		$grid = new DataGrid($this, $name);
		// zde by se nastavovaly šablony
		return $grid;
	}
}

Compile Error
Interface function Moje\DataGrid\IDataGridFactory::create() cannot contain body

Asi to bude nějaká prkotina jak se znám, ale budu rád za nápovědu.

Ještě jedna otázečka: co prosím znamenají parametry konstruktoru $this a $name $grid = new DataGrid($this, $name);?

Editoval flamengo (11. 8. 2016 11:01)

Pavel Janda
Člen | 977
+
0
-

@flamengo EDIT: Pleteš asi víc věcí dohromady. Ty jsi chtěl vytvářet funkcionalitu metody v Interface, to v PHP nelze… To může dělat třída, která Interface dědí.

Doporučuji přečíst (celý článek): https://doc.nette.org/…n/components#…

Buď můžeš vytvořit komponentu takto:

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

		return $grid;
	}
}

nebo takto:

My Presenter
{
	public function createComponentGrid($name) // $name = 'grid'
	{
		$grid = new DataGrid($this, $name);
	}
}

Všimni si, že už u druhého příkladu nemusíš uvádět return statement. Proč – to se dozvíš ve výše zmíněném článku. Jde o moment, kdy se komponenta přiřazuje k rodiči (jiné komponentě/prsenteru). A pokud bych měl u obou příkladů použít factory na grid, bude to vypadat asi takto:

Buď můžeš vytvořit komponentu takto:

My Presenter
{
	/**
     * @var GridFactory
     * @inject
     */
	public $gridFactory

	public function createComponentGrid()
	{
		$grid = $this->gridFactory->create();

		return $grid;
	}
}

class GridFactory
{
	public function create()
	{
		return new \Ublaboo\DataGrid\DataGrid;
	{
}

nebo takto:

My Presenter
{
	/**
     * @var GridFactory
     * @inject
     */
	public $gridFactory

	public function createComponentGrid($name) // $name = 'grid'
	{
		$grid = $this->gridFactory->create($this, $name);
	}
}

class GridFactory
{
	public function create($parent, $name)
	{
		return new \Ublaboo\DataGrid\DataGrid($parent, $name);
	{
}

V tomhle případě ta factory nepotřebuje žádné závislosti, tak nemusíš řešit žádný Interface..

Editoval Pavel Janda (11. 8. 2016 11:20)

flamengo
Člen | 131
+
0
-

@PavelJanda Děkuji, vůběc mi nedošlo, že tam mám interface :( Zkopíroval jsem si jinou továrničku a nevšiml si toho, takže moje chyba.

No a asi tě moc nepotěším, ale mám další várku dotazuů ehm.

1/ Šlo by prvek Ublaboo\DataGrid\Toolbar opatřit možností setConfirm()? Sice jsem si to tam dodělal, ale opět do vendoru :(

2/ Při úpravě Toolbaru jsem si všiml asi nedodělku, nepřekládá se text butonku.

$a->addText($this->text); // řádek 63
// asi nahradit:
$a->addText($this->grid->getTranslator()->translate($this->text));

3/ Bylo fajn mít možnost místo textového tlačítka Toolbar umístit ikonku, ale to si klidně dodělám.

4/ Jak lze vyresetovat třídění? Mám pocit, že někde jsem četl v dokumentaci, že se vše ukládá do session, ale potřeboval bych tlačítko „Výchozí řazení“, nebo tak něco. Udělal bych si ho jako Toolbar, ale jak to vyresetovat?

5/ Funkce metody $grid->setSortableResetPagination(); se mi moc nepozdává. Při třídění na sloupci name se paginator nastavil na stránku č.1 pouze při změně na grid-sort[name]=DESC (parametry URL). Nebo tuto funkci chápu špatně?

$grid->addColumnText('name', 'forms.inputs.name')
	->setSortable()
	->setSortableResetPagination();

6/ Lze setSortableResetPagination(); nastavit pro celý datagrid najednou?

7/ Nastavení $grid->setDefaultSort(['price' => 'DESC']); nic nedělá, ale to bude asi tím, že už nějaké hodnoty jsou v session. Toto tedy platí pouze pro první zobrazení?

Opět předem velké díky za reakci.

unnamed21
Člen | 3
+
+1
-

Ahoj,
otázka ohľadom addColumnLink a addAction – je možné (ako ?) nastaviť parametre params, ktoré by mali parametrizovať výsledný href odkaz tak, aby som do nich dostal vlastné parametre, resp. nečerpané zo stĺpcov DataGridu ?

<?php
$grid = new DataGrid($this, $name);

$grid->setDataSource($this->structure->articles);

$grid->addColumnText('id', '#ID', 'id');

// vysledny link = cms.cms-administration/edit/15
$grid->addColumnLink('articleLabel', 'Article Label', ':Cms:CmsAdministration:edit', 'label', [ 'id' => 'id'] );

// vysledny link = cms.cms-administration/edit/15
// 'type' => 'article' je ignorovane
$grid->addColumnLink('articleLabel2', 'Article Label', ':Cms:CmsAdministration:edit', 'label', [ 'id' => 'id', 'type' => 'article'] );
?>

Občas je potreba link vytvoriť trochu custom, napríklad pridanie konštanty, ktorá v datagride nie je definovaná, čo je vlastne aj prípad kedy som narazil na tento problém. Pridanie columnLinku articleLabel2 teda ignoruje parameter ‚type‘ ⇒ ‚article‘ a výsledný odkaz je potom totožný ako columnLink articleLabel.

ublaboo/datagrid v4.4.9
nette/application v2.3.13

Ďakujem

Editoval unnamed21 (11. 8. 2016 23:39)

Pavel Janda
Člen | 977
+
0
-

@flamengo

  1. Šlo, můžeš poslat PR. :) Podle vzoru Action
  2. Můžeš poslat PR. :)
  3. Můžeš poslat PR. :)
  4. Na webu dokumentace ho nevidíš? (http://ublaboo.org/datagrid), vpravo dole, velké červené tlačítko s nápisem RESET FILTER
  5. Pokud má sloupec takovýto příznak, tak po každé směně řazení podle tohoto sloupce se uživatel octne na první stránce.
  6. Nope. Můžeš poslat PR. :)
  7. Ano, kdyby jsi chtěl násilně filtry změnit, existuje metoda ::setFilter().

@unnamed21 Je, přes custom renderer, nebo šablonu. Ale můžeš poslat PR, aby se daly další parametry přidávat nějakou další metodou. To, co jsi zkoušel (['id' => 'name']), vyrábí něco jiného, viz dokumentace: http://ublaboo.org/datagrid/column#…

esorimer
Člen | 114
+
0
-

Ahoj,
existuje, nebo bude existovat nějaká podpora pro Paginator ?
Bez toho nefunguje stránkování s Doctrine správně :(

Pavel Janda
Člen | 977
+
0
-

@esorimer Tento datagrid tebou zmíněný Paginator používá. Viz:
count: https://github.com/…taSource.php#…
limit: https://github.com/…taSource.php#…

esorimer
Člen | 114
+
0
-

Pavel Janda napsal(a):

@esorimer Tento datagrid tebou zmíněný Paginator používá. Viz:
count: https://github.com/…taSource.php#…
limit: https://github.com/…taSource.php#…

Ten limit právě nefunguje správně.

Mám tabulku A, která má vztah 1:M s tabulkou B.
Když udělám dotaz, kde chci vše z A, co má konrétní záznam z B (B.id = 123),
uká že mi DataGrid výsledek „Zobrazuji 1–5 z 9 záznamů“ (Žádné stránkování,přičemž limit je na dataGridu nastaven na 10).

Tj. správně to ukáže, že má zobrzit 9 záznamů, ale zobrazí to jen 5.

To je proto, protože 5 záznamů z A má (v průměru) dvě relace s B, tj. po JOINu zaberou dohromady 10 řádků – limit datagridu).

Edit:
Tak když nahradím tuto řádku https://github.com/…taSource.php#L99
za return new Doctrine\ORM\Tools\Pagination\Paginator($this->getQuery());
tak to funguje správně. Takže díky za nápovědu :)

Editoval esorimer (17. 8. 2016 14:48)

Pavel Janda
Člen | 977
+
0
-

@esorimer Díky za upřesnění. Nechtěl bys poslat PR, který by přes nějaký setter DataGrid řekl doctrine datasourceu, aby používal ten paginator, jak píšeš? Tedy že by by default používat stávající verzi, ale uživatel si mohl volit i tebou zmíněnou?

rumcais1
Člen | 80
+
0
-

Koukám na příklad s tree-view a moc nerozumím dotazu
$join = $this->db->select(‚id, parent_category_id‘)
->from(‚ublaboo_category‘)
->groupBy(‚parent_category_id‘);

To přece nemůže fungovat.:-) Díky

Pavel Janda
Člen | 977
+
0
-

@rumcais1 Musíš to ponechat v kontextu, v jakém se to objevilo na webu dokumentace, tedy:

$join = $this->db->select('id, parent_category_id')
	->from('ublaboo_category')
	->groupBy('parent_category_id');

$fluent = $this->db
	->select('c.*, c_b.id as has_children')
	->from('ublaboo_category', 'c')
	->leftJoin($join, 'c_b')
		->on('c_b.parent_category_id = c.id');

Select kategorií musí obsahovat informaci o tom, zda má kategorie nějaké podkategorie (has_children).

Kapišto?

CZechBoY
Člen | 3608
+
0
-

@PavelJanda myslím že @rumcais1 naráží na to, že se používá GROUP BY aniž by se selectovala nějaká agregovaná funkce.

Pavel Janda
Člen | 977
+
0
-

@CZechBoY Jasně. Tak pokud má člověk striktnější náladu nebo nastavení direktiv, tak to může napsat lépe. Těch způsobů je nesčetně mnoho. Pointa je čistě v připojení alespoň jednoho potomka ke kategorii. Je to tak pochopitelné, @rumcais1?

flamengo
Člen | 131
+
0
-

@PavelJanda

Můžeš poslat PR. :)

Když to já bohužel neumím a nerad bych něco pokazil :(

4. Na webu dokumentace ho nevidíš? (http://ublaboo.org/datagrid), vpravo dole, velké červené tlačítko s nápisem RESET FILTER

Reset tlačítko je vidět až v případě, že je nějaký filtr aktivní jsme zjistil. Nicméně já pouze potřebuji resetovat způsob řazení položek na výchozí, nikoliv filtrování.
Přijde mi to dost důležité kvůli tomu, aby si uživatel mohl řazení vyresetovat a vidět tak, v jakém pořadí se položky zobrazí na front-endu. Dodělal jsem si metodu a v šabloně k tomu odpovídající tlačítko:

public function handleResetSort(){
	$this->page = 1;
	$this->saveSessionData('_grid_page', 1);
	$this->sort = $this->default_sort;
	$this->saveSessionData('_grid_sort', $this->sort);
	$this->reload(['grid']);
}

5. Pokud má sloupec takovýto příznak, tak po každé směně řazení podle tohoto sloupce se uživatel octne na první stránce.

Ať testuji jak testuji, tak opravdu mi to nefungovalo jak by mělo. Nakonec záhada odhalena. V metodě handleSort() se reloaduje pouze snippet table, Chce to přidat

$this->reload(['pagination']);

nebo překreslit celý grid.

ŠABLONA PAGINATORU
Ještě dotaz k šabloně paginatoru. Asi to zase bude nějaká hloupost. Pokud jsem oprpavil zdroják (výše), tak vše funguje pouze v případě původní šablony. Jakmile dle kódu níže načtu svou šablonu (i když je identická s původní), tak se paginator nepřekresluje a nefunguje ani překlad translator. Netuším, čím by to mohlo být.

use Ublaboo\DataGrid\DataGrid;
class DataGridFactory{
	/** @return DataGrid */
	public function create($parent, $name = 'grid'){
		$grid = new DataGrid($parent, $name);
		$grid->getPaginator()->setTemplateFile(__DIR__ . '../moje/data_grid_paginator.latte');
		return $grid;
	}
}

SLOUPEC TYPU „TIME“
Dále jsme narazil asi na chybu, nebo opět dělám něco špatně.

MySQL tabulka:

CREATE TABLE dates (
id int(11) UNSIGNED NOT NULL,
date date DEFAULT NULL,
time_from time DEFAULT NULL,
time_to time DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;

INSERT INTO dates (id, date, time_from, time_to) VALUES (1, ‚2016–11–11‘, ‚23:59:00‘, ‚00:00:00‘);

A chci zobrazit sloupec typu „time“:

$grid->addColumnDateTime('time_from', 'forms.inputs.time_from');

Zobrazí se chyba:
Warning
DateTime::createFromFormat() expects parameter 2 to be string, object given

File: …\ublaboo\datagrid\src\Utils\DateTimeHelper.php:28

23:        public static function tryConvertToDateTime($value)
24:        {
25:            /**
26:             * Try to convert string Y-m-d to DateTime object
27:             */
28:            $date = \DateTime::createFromFormat('Y-m-d', $value);

EDIT:
Při pokusu zobrazit sloupec „time“ jako text:

$grid->addColumnText('time_from', 'forms.inputs.time_from');

Warning
htmlspecialchars() expects parameter 1 to be string, object given

File: …\vendor\latte\latte\src\Latte\Runtime\Filters.php:47

43:        public static function escapeHtmlText($s)
44:        {
45:            return $s instanceof IHtmlString || $s instanceof \Nette\Utils\IHtmlString
46:                ? $s->__toString(TRUE)
47:                : htmlSpecialChars($s, ENT_NOQUOTES, 'UTF-8');

Nevíš prosím, co je špatně?

Předem díky moc.

Editoval flamengo (18. 8. 2016 13:26)

rumcais1
Člen | 80
+
0
-

Díky zkoušel jsem to na mssql. A tam to takhle nejde. Díky

esorimer
Člen | 114
+
0
-

Pavel Janda napsal(a):

@esorimer Díky za upřesnění. Nechtěl bys poslat PR, který by přes nějaký setter DataGrid řekl doctrine datasourceu, aby používal ten paginator, jak píšeš? Tedy že by by default používat stávající verzi, ale uživatel si mohl volit i tebou zmíněnou?

No já tomu zas tak moc nerozumím. Nevím např. k čemu je tam to $this->data. $data je protected a nikde se do něj nepřiřazuje. Dle té poznámky ve funkci getData() to vypadá, jako by to někdo chtěl řešit v potokovi, ale kdo ví.

Já to vyřešil jednoduše rozšířením DataGridu a DoctrineDataSource:

<?php

namespace App\Lib;

use Ublaboo\DataGrid\DataGrid as DG;
use Ublaboo\DataGrid\DataSource\DoctrineDataSource;

class DataGrid extends DG
{
    public function setDataSource($source) {
		return parent::setDataSource(new DoctrinePaginator($source, $this->primary_key));
    }
}

class DoctrinePaginator extends DoctrineDataSource
{
	public function getData() {
	    return new \Doctrine\ORM\Tools\Pagination\Paginator($this->getQuery());
	}
}
?>

Asi by nebyl problém přidat nějaký flag do konstruktoru DoctrineDataSource, ale kvůli „primary_key“ parametru by nebylo hezký, aby ho musel programátor sám instanciovat.
Možná bych na to vytvořil nějakou hloupou obálku, něco jako:

<?php
class Ublaboo\DataGrid\DoctrinePaginator {
    public function __construct(QueryBuilder $qb) {
        $this->qb = $qb;
    }
	//...
}
//.... a pak v konstruktoru Ublaboo\DataGrid\DataModel přidal podmínku:
if($source instanceof DoctrinePaginator) {
		$source = new DataSource\DoctrineDataSource($source->getQueryBuilder(), $primary_key, $usePaginator=TRUE);
}
?>

iNviNho
Člen | 352
+
0
-

Ahojte,

Skúšam už druhý deň tento doplnok a veru autor si dal s tým naozaj kopu kvalitnej práce. Ponoril som sa do toho a asi jediné, čo mi ostáva a čo mi robí problémy je nájsť a zavolať nejaky callback po re-rendernutí datagridu. Akonáhle si napríklad schovám nejakú column, alebo sortnem podľa niečoho, tak sa re-renderne formulár a prestane mi fungovať môj custom checkbox na ktorý som pri načítani stránky cez JS zavolal plugin bootstrapSwitch…

Potreboval by som iba jednoducho po rendere bud načítať moj vlastný block, alebo niekde pichnuť ten JS pre inicializáciu bootstrapSwitch pluginu.

Neviete mi poradiť? Ďakujem!

Pavel Janda
Člen | 977
+
+2
-

@iNviNho Dej si někam do JS souboru:

$.nette.ext('bootstrapSwitch', {
	success: function(payload) {
		$('.bootstrapSwitch').bootstrapSwitch();
	}
});

Co se stane: Určitě používáš (používá to i ublaboo/datagrid), nette.ajax.js (https://componette.org/search/?…). Kód výše ti po dokončení nette ajax requestu inicializuje ty switche.

Editoval Pavel Janda (18. 8. 2016 20:38)

mirek.vales
Člen | 2
+
0
-

Zdravím. Chválím také autora gridu za výbornou práci, pár dní procházím kódy. Snad můj dotaz patří do tohoto fóra. Po inline editaci řádku ($grid->getInlineEdit()->onSubmit[]…) se mi v gridu neukáže změněná hodnota položky. Obdobné je to při mazání řádku. Funkce po odeslání formuláře provede SQL dotaz a do databáze uloží novou hodnotu. Po reloadu stránky v browseru (F5) nová hodnota zde je. Vše volám dle dokumentace (if ($this->isAjax()) {$this->redrawControl(‚flashes‘); $this[‚myGrid‘]->reload();}. Řádek po uložení na chvíli zezelená – $.nette.init() načítám. Snippety se invalidují, jen např. v snippet-myGrid-item-2 mi do prohlížeče posílá původní hodnoty (před změnou položky). Zkoušel jsem i jiné pořadí snippetů, snippetArea i další věci. Už opravdu nevím, kde můžu dělat chybu. Díky za radu!!!
edit: koukám i na http://ublaboo.org/datagrid/action a to také nepomohlo

Editoval mirek.vales (19. 8. 2016 11:48)

Pavel Janda
Člen | 977
+
0
-

@mirek.vales Používáš ArraDataSource, že? :P

Pavel Janda
Člen | 977
+
0
-

@mirek.vales Doporučuji přečíst si tento a po něm jdoudí 3 komentáře: https://forum.nette.org/…any-datagrid?p=10

mirek.vales
Člen | 2
+
0
-

Pavel Janda napsal(a):

@mirek.vales Doporučuji přečíst si tento a po něm jdoudí 3 komentáře: https://forum.nette.org/…any-datagrid?p=10

Moc díky za rychlou reakci. ArrayDataSource jsem nepoužíval. Pomohla funkce onCustomRedraw (viz.poslané 3 komentáře), kdy mi nedošlo, že po uložení dat do databáze je pro opakované zobrazení ve stránce ještě musím znovu načíst z databáze (a následně volat invalidaci snippetů).

			$grid->getInlineEdit()->onCustomRedraw[] = function() use ($grid) {
				$grid->setDataSource($this->db->query('SELECT id,name FROM myTable')->fetchAll());
				$grid->redrawControl();
			};
Pavel Janda
Člen | 977
+
0
-

@mirek.vales Načtení dat znovu z databáze je potřeba jen a pouze při použití pole jako zdroje dat. A ty používáš pole jako zdroj dat. (::fetchAll() ti vrátí pole)

Používáš Nette\Database. Pokud to chceš mít lazy a super a všechno (prostě nepoužívat takhle fetchAll() a pole), doporučuji prozkoumat http://ublaboo.org/…data-source/ . Tento jediný grid umí pracovat s Nette\Database skrze zmíněný datasource.

Nebude pak potřeba ten ::$onCustomRedraw callback apod.

Editoval Pavel Janda (19. 8. 2016 13:57)

Bogi
Člen | 24
+
0
-

Zdravíčko! Předně děkuji za skvělý datagrid, je to fakt pecka! :)
Mám dotaz, je možné používat MultiSelect i na sloupec, který má hodnoty NULL v databázi?

Konkrétně vypisuju kategorie, do kterých patří produkty z e-shopu, ale některé produkty nemají kategorii (mají NULL hodnotu u kategorie). Chtěl bych, aby bylo možné filtrovat i produkty bez kategorie, ale pokud filtruju produkty Bez kategorie následujícím způsobem, filtr pro NULL hodnotu nefunguje resp. zobrazuje stále všechny produkty:

$categories = $this->db->table('eshop_categories');
$categoryMap = [];
foreach ($categories as $category) {
    $categoryMap[$category->id] = $category->name;
}
$categoryMap[null] = 'Bez kategorie';
$grid->addColumnText('category', 'Kategorie')
    ->setReplacement($categoryMap)
    ->setFilterMultiSelect($categoryMap);
iNviNho
Člen | 352
+
0
-

Ahoj,

dnes vytváram prvý inline edit a mám problém s 2 vecami. Ako prvá je, že po odoslaní novej hodnoty v inline edite sa mi do metody payedAmountEdited odosiela iba ID riadku, ale nie jeho nová value

// add ColumnNumber
$grid->addColumnNumber("payedAmount", "Uhradená suma")
                ->setAlign("center")
                ->setFormat(2, ".", " ")
                ->setRenderer(function($item) {
                    return $item->getPayedAmount() . " €";
                })
                ->setEditableCallback([$this, "payedAmountEdited"])
                ->setEditableInputType('text', ['class' => 'form-control']);

// $value je vždy NULL
public function payedAmountEdited($id, $value) {
    dump($id);
    dump($value);
}

a druhá vecička je, či je možné použiť nejaky callback po vytvorení políčka pre edit. Kedže v tabuľke vypisujem nezapltenú čiastku a pridávam jej menu v €, tak sa mi automaticky do tohto pola vopchá aj € znak a to nechcem :)

Ďakujem za rady a pomoc :)

-- EDIT
Po premazaní cachu už to funguje ako má :) Čiže by ma zaujímal iba ten druhý bod, ak neexistuje callback, tak vymyslím nejaké vlastné riešenie :)

Editoval iNviNho (22. 8. 2016 13:45)

FTCP
Člen | 6
+
0
-

Ahoj, už tu byl dotaz na link s parametrem/parametry a odpovídal jsi že se dá použít custom renderer, bohužel když ho takto použiju, celý html prvek <a> se vypíše jako text, dá se tomu nějak zabránit ? či je jiný způsob vytvoření custom linku ?

<?php
$grid->addColumnLink('now', 'Vytvořeno', 'Action:edit' , 'now', ['id' => 'row_id'])
		->setRenderer(function($row)
			{
			$test = "<a class='' href='/action/edit/".$row->row_id."?backlink=xyzž'>".$row->now."</a>";
             return $test;
			})
?>
Pavel Janda
Člen | 977
+
+2
-

@FTCP Column::setTemplateEscaping(FALSE), viz dokumentace (Column escaping): http://ublaboo.org/datagrid/column

CZechBoY
Člen | 3608
+
+1
-

@ftcp nešlo by to obejít vytvořením Nette\Utils\Html objektu? + použít nette generátor odkazů

Editoval CZechBoY (24. 8. 2016 11:12)

iNviNho
Člen | 352
+
0
-

Chalani neriešili ste niekedy ako prekladať samotné texty datagridu ak používate Kdyby\Translation?

Kdyby požaduje preklady vo formáte boo.foo.neco … Datagrid ich má vo forme foo.neco, čiže ublaboo_datagrid.save nedokážem v kdyby/translation preložiť?

Možno by nebolo zlé pridať možnosť akéhosi prefixu týchto prekladov, že by som si iba pridal prefix prekladu napr. „is.“ a už by som mohol prekladať, pretože by kľúče pre preklady vyzerali „is.ublaboo_datagrid.save“.

jiri.pudil
Nette Blogger | 1028
+
+4
-

Přiznávám, že střílím od boku, ale tipnul bych si: co je před první tečkou, použije se jako doména, tj. název neon souboru bude ublaboo_datagrid.%locale%.neon, no a zbytek je cesta v poli – v tomto případě tedy bude jednorozměrné:

save: Uložit
cancel: Storno
...
iNviNho
Člen | 352
+
0
-

@jiri.pudil génius, funguje

Domki
Člen | 310
+
0
-

Používám jako datasource Yetorm a v entitě mám funkci getProductsWithBrand() vracející počet produktů
Jak můžu tuto hodnotu přidat do datagridu, nevím jak k ní přistoupit v funkci addColumnText

$grid->addColumnText('co tady?', 'Počet produktů');

Podobný problém mám i když chci ziskat jen odkaz na jinou entitu. řešení jako je v dokumentaci pro Doctrine mi nefunguje(nezna sloupec).
Děkuji za pomoc

Editoval Domki (24. 8. 2016 20:48)

Pavel Janda
Člen | 977
+
0
-

@Domki To bude pravděpodobně tím, že pro doctrine (, nextras a leanmapper) entity jsem implementoval lehce širší property access věc. Můžeš poslat PR s přidáním yetorm-related-stuff. A nebo založ issue, popiš v ní, jak se chovají entity v yetorm (nebo přilož nějakou dokumentaci) a já se na to o dovolené podívám. :)

Určitě bude dobré to přidat.

Domki
Člen | 310
+
0
-

Ok s gitem ale tolik neumím, takže uplně moc nevím kde založit issue?

Ono já tedy teď používám přes getTable z YetOrm ActiveRow, protože jako datasource nešel YetOrm přidat. Což mi bylo poraděno cca před měsícem tady.

Pavel Janda napsal(a):

@Domki To bude pravděpodobně tím, že pro doctrine (, nextras a leanmapper) entity jsem implementoval lehce širší property access věc. Můžeš poslat PR s přidáním yetorm-related-stuff. A nebo založ issue, popiš v ní, jak se chovají entity v yetorm (nebo přilož nějakou dokumentaci) a já se na to o dovolené podívám. :)

Určitě bude dobré to přidat.

Editoval Domki (25. 8. 2016 10:44)

Pavel Janda
Člen | 977
+
0
-

@Domki Aha, ale pokud používáš jako datasource NDBT\Selection, pak nepoužíváš entity.

Domki
Člen | 310
+
0
-

Jo já vím již dříve jsem se tu ptal jestli je možnost využívat YetOrm a entity, co jsem pochopil, tak jako datasource yetorm nelze využít.
Pak mi @PavelKravčík napsal že můžu použít převod getTable na Selection.
Ale pak nevím jak přidat sloupce z jiných tabulek propojených cizím klíčem. (Právě v entitě využívaných danou funkcí). Jestli je nějaká možnost když Yetorm(entitu) převedu na NDBT/Selection?

Nebo možno přidat podporu i přímo pro Yetorm?

@PavelKravčík

Pavel Janda napsal(a):

@Domki Aha, ale pokud používáš jako datasource NDBT\Selection, pak nepoužíváš entity.

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

Pokud to není veliká tabulka většinou je nejjednodušší rešení:

	$repository("SELECT t.foo, a.bar FROM table t LEFT JOIN another a ON a.id = t.a_id")->fetchAll();

Anebo asi lepší:

http://ublaboo.org/…data-source/

Pavel Janda
Člen | 977
+
0
-

@Domki Ano, přesně jak zmínil @PavelKravčík – pokud chceš položit složitější dotaz přes NDB::query(), použij zmíněný ublaboo/datagrid-nette-database-data-source. Dovolí ti složité dotazy a přitom se nebude fetchovat do paměti celá databáze :) .