Grido – DataGrid pro Nette
- Tirus91
- Člen | 199
@o5
Prosím tě, jak mohu vypnout ajax (v JS jsem uvedl false, ale i tak to blbne)
a jak mohu zaměnit datepicker za svůj vlastní? Když jsem si v Date.php
zaměnil jen tu třídu ‚date‘ za ‚datepicker‘ tak sice můj kalendář
se vyvolal, ovšem následně po kliknutí mimo nbeo na jiný prvek mi ta
hodnota zmizela (v jiném formuláři/komponentě než GRIDO mi to
funguje).
protected function getFormControl()
{
$control = parent::getFormControl();
$control->getControlPrototype()->class[] = 'datepicker';
$control->getControlPrototype()->attrs['autocomplete'] = 'off';
return $control;
}
- Pavel Kravčík
- Člen | 1195
@o5: Nešlo by přidat něco na způsob:
$grid->setHeaderRowCallback('buttons');
Rád bych si trochu upravil tlačítka Vyhledat a Reset (http://imgur.com/nxjlgLo). Přes lokalizaci můžu měnit popisek, ale do value="" ikonku nedostanu.
Nebo mi napadá ještě změnit {formContainer buttons}{/form}
na manuální vykreslování a místo input použít <button>sem vypsat
lokalizaci</button>.
- Pavel Kravčík
- Člen | 1195
@Desttro: http://o5.github.io/…tion.cs.html#…
$grid->setRowCallback(function($row, Html $tr)
{return $tr});
- Desttro
- Člen | 126
kzk_cz napsal(a):
@Desttro: http://o5.github.io/…tion.cs.html#…
Děkuji, příště si projedu dokumentaci kompletně celou.
- o5
- Člen | 416
kzk_cz napsal(a):
Nebo mi napadá ještě změnit
{formContainer buttons}{/form}
na manuální vykreslování a místo input použít <button>sem vypsat lokalizaci</button>.
Můžeš použít vlastní šablonu, kde překryješ blok action a vypíšeš si vlastní formulářové prvky. Budeš ale muset asi překrýt i metodu Grid:createComponentForm aby to nebyl input ale button.
{extends path/to/vendor/grido/Grid.latte}
<th class="buttons" n:block="action">
{formContainer buttons}
{input search, title => 'Použít filtr', value => '↳', class => 'btn btn-default btn-xs'}
{input reset, title => 'Resetovat filtr', value => '⟲', class => 'btn btn-default btn-xs'}
{/formContainer}
</th>
S tím button[type=submit] se to chovalo různě napříč browsery, když jsem to kdysi zkoušel.
- Desttro
- Člen | 126
Podporuje Grido SubGridy? např: http://www.grid.jakubholub.cz/subgrid
Editoval Desttro (18. 2. 2015 10:54)
- Ja
- Člen | 260
Ted jsem vyresil jednu vec, ale vrta mi hlavou, zda to jde i jinak.
Mam dve stranky:
- SEKCE (SectionPresenter)
- STRANKY (PagePresenter)
STRANKY spadaji pod prave 1 SEKCI
Mam grido na vypis sekci a chci se z neho prokliknout na Page:default,id_section=X
Ackoli mam definovano v PagePresenter:
<?php
public function actionDefault($id_section){}
?>
tak mi to grido stale preklada na odkaz /page/?id=X… (id odpovida sloupci ID v SECTION tabulce). Da se prinutit, aby smeroval na jiny presenter i s takto pozmenenym nazvem parametru?
- Jan Mikeš
- Člen | 771
Ahoj, nechce mi fungovat suggestions nad text columnem s doctrine data
sourcem.
S doctrine jsem zacal dost cerstve, nevim tedy jestli se jedna o chybu na me
strane nebo bug v gridu – prosim o nakopnuti.
InvoicingData service – ziskani QB:
public function getUserInvoicingData(Entities\User $user)
{
return $this->invoicingDataDao->createQueryBuilder("a")
->where("a.user = :user")
->setParameter("user", $user);
}
Grid:
protected function createComponentGrid($name)
{
$grid = new Grido\Grid($this, $name);
$grid->translator->setLang("cs");
$grid->filterRenderType = Grido\Components\Filters\Filter::RENDER_INNER;
$grid->setModel($this->invoicingData->getUserInvoicingData($this->user->getIdentity()));
$grid->setDefaultSort(["name" => "ASC"]);
$grid->addColumnText("name", "Subjekt")
->setSortable()
->setFilterText()
->setSuggestion();
return $grid;
}
Pokud odstranim ->setSuggestion() vse funguje OK (i filtrovani, i razeni…). Pokud ale zacnu psat do filtru a chvilku pockam (je tam rekl bych timeout na event, nez se odpali dotaz do db..), tak se objevi exception
Doctrine\ORM\Query\QueryException
[Semantical Error] line 0, col 116 near ‚name ASC‘: Error: ‚name‘ is
not defined.
Vygenerovane DQL:
SELECT DISTINCT a.name
FROM App\Model\Entities\InvoicingData a
WHERE a.user = :user AND a.name LIKE :ssxe0
ORDER BY name ASC
Rekl bych, ze v DQL chybi a. pred name v ORDER BY klauzuli.
- raketoplan2005
- Člen | 147
Ahoj,
mám např. tabulku objednávek s joinem do tabulky projektů. Sloupec
z joinované tabulky si v selectu pojmenovávám např. jako
project_name
.
V gridu pak zobrazuji přehled objednávek a k nim i název projektu, ke kterému se váže.
Ve sloupci s názvem projektu bych chtěl ale nejen povolit filtr
(setFilterText()
s setColumn('project.name')
funguje),
ale také našeptávat. Tuto kombinaci ale neumím zprovoznit.
Grido mi totiž pro suggestion udělá:
SELECT DISTINCT project_name FROM...
což narazí na to že project_name
neexistuje. Když do
‚setSuggestion()‘ přidám setSuggestion('project.name')
tak
skončím naopak s:
Undefined property: DibiRow::$project.name
Jak bych měl prosím toto řešit správně? Děkuji
Editoval raketoplan2005 (26. 2. 2015 16:28)
- pepakriz
- Člen | 246
@raketoplan2005 V druhém případě když použiješ SymfonyPropertyAccessor, tak ti to možná bude fungovat.(viz https://github.com/…Accessor.php)
- raketoplan2005
- Člen | 147
@pepakriz :
Děkuji za rady, nevím jestli jsem udělal vše co je nutné, ale přes
composer jsem stáhl symfony/property-access
a přidal jsem do
komponenty
$propertyAccessor = new \Grido\PropertyAccessors\SymfonyPropertyAccessor();
$grid->setPropertyAccessor($propertyAccessor);
Vše se chová stejně a to takto:
- pokud mám jen filtr bez našeptávání se
setColumn('project.name')
tak to filtruje správně - pokud mám jen filtr s našeptáváním
setSuggestion('project.name')
a obecnýmsetColumn()
, tak to data pro suggestion hledá správněDISTINCT project.name
ale vypadnu na filtrku, protože ve WHERE je to jenname LIKE %foo%
–Column 'name' in where clause is ambiguous
- pokud mám
setColumn('project.name')
asetSuggestion('project.name')
pohromadě tak končím sUndefined property: DibiRow::$project.name
Editoval raketoplan2005 (26. 2. 2015 16:59)
- o5
- Člen | 416
@raketoplan2005: Změna PropertyAccess to neřeší, koukni do grido-examples, tam se našeptává sloupec country který je najoinovaný.
- raketoplan2005
- Člen | 147
@o5:
Fajn, děkuji tohle zafunguje. Ale co v případě, když joinuji dvě tabulky,
např. projekt a společnost?
$grid->addColumnText('project_name','Projekt')
->setSortable()
->setFilterText()
->setColumn('project.name')
->setSuggestion('name');
$grid->addColumnText('company_name','Společnost')
->setSortable()
->setFilterText()
->setColumn('company.name')
->setSuggestion('name');
To pak narazí na stejně pojmenované sloupce name –
Column 'name' in field list is ambiguous
. To je taky v Gridu
řešitelné, nebo už mě to směřuje na view?
- Tirus91
- Člen | 199
@o5
Ahoj,
prosím tě, mám pár otázek. Jde nějak upravit šablona pro Grido, aby
vypadala nějak následovně?
Obrázek
z Admin LTE2
Jde mi hlavně o to stránkování a hromadné akce. U těch akcí že by to nebyl číselník, ale tlačítka nahoře. (místo názvu by byl class). Dále ještě zda jde všechny filtry (cca 4 sloupečky) navázat na jeden input.
Díky, Tirus
- o5
- Člen | 416
@raketoplan2005: ono to dost dobře automaticky udělat nejde a tedy pro tyto účely je tam metoda setSuggestionCallback().
@Tirus91:
Jde nějak upravit šablona pro Grido, aby vypadala nějak následovně
jde
Dále ještě zda jde všechny filtry (cca 4 sloupečky) navázat na jeden input
jde, přes setColumn(). Stačí se podívat na jeden z examplů.
Editoval o5 (2. 3. 2015 12:20)
- Pavel Kravčík
- Člen | 1195
@Tirus91: A ty to chceš změnit celé? Proč nezkusit něco podobného:
class MyGrid extends \Grido\Grid
{
/**
* Override
* @see parent
*/
public function createTemplate($class = NULL)
{
$template = parent::createTemplate($class);
$template->setFile(__DIR__ .'JardaJagr.latte');
return $template;
}
}
- Pavel Kravčík
- Člen | 1195
@o5: Moje chyba. Nečekal jsem, že tam něco takového bude, když se na to ptal. :)
- Pavel Janda
- Člen | 977
Zdravíčko,
@o5
na Nette 2.3 blbnou v Grid.latte nějaká malá písmenka Presenterů
(zmiňovaný BC break).
User Warning
Case mismatch on presenter name 'Front:story', correct name is 'Front:Story'.
Lajna 165
164: <?php $iterations++; } if ($showActionsColumn) { ?> <td class="actions center">
165: <?php $iterations = 0; foreach ($actions as $action) { if (is_object($action)) $_l->tmp = $action; else $_l->tmp = $_control->getComponent($action); if ($_l->tmp instanceof Nette\Application\UI\IRenderable) $_l->tmp->redrawControl(NULL, FALSE); $_l->tmp->render($row) ;$iterations++; } if (!$actions) { ?>
166:
Edit:
Omluvám se, blbost je v kódech dotyčného.
Editoval Beton (5. 3. 2015 14:13)
- kolsi
- Člen | 131
Lze u Grida nějak elegantně přizpůsobit šířku sloupce obsahu?
Řekněme, že mám Grido, které obsahuje více sloupců, z nichž některý obsahuje třeba jenom ANO/NE. Přesto tento sloupec dostane větší šířku, která způsobí, že jiný sloupec obsahující delší obsah se zalomí a výsledek pak nevypadá pěkně. Kdyby ten krátký sloupec se automaticky přizpůsobil, tak by k zalomení vůbec nedošlo.
- Šaman
- Člen | 2659
o5 napsal(a):
@Šaman máš to v masteru.
takové identifikační třídy hodily i na další prvky
konkrétně?
Ahoj, díky. Konkrétně jsem na to teď koukal a pokud se rozdělí class
count
pro paginátor od export
u, tak to bude
v pohodě.
Ještě řeším jeden problém – mám v zadání, že tlačítko pro export
má být mimo grid. Ok, vytvořil jsem si ho a odkazuji se na akci gridu pomocí
n:href="personGrid-export-export!"
Problém je, že takovýto odkaz
nezohledňuje filtry. Dokonce ani když jsem se zkušel hacknout Grido a vypsat
si odkaz přímo z něho, tak se mi filtry ignorovaly. Začínám mít dojem,
jestli ty filtry (jejich dodání do adresy) nejsou v režii nějakého JS.
Můžeš mě kopnout správným směrem, pokud chci tlačítko umístit mimo
grid, pls?
- o5
- Člen | 416
mpis napsal(a):
Co je čistší? Persistentní komponenta nebo $grid->setRememberState()?
To IMHO nejde takto jednoznačně říci. Pokud ta editační akce je v rámci stejného presenteru, tak to stačí vyřešit persistetní komponentou. Já ale všude, kde mám nasazené Grido, nastavuju ukládání stavu do sessions jako výchozí, protože je to prostě více uživatelsky přívětivé.
- Šaman
- Člen | 2659
o5 napsal(a):
@Šaman: takhle ti to půjde:
$this['grid']['export']->link('export!')
Bohužel, tohle mi taky odřízne nastavení filtrů. Nicméně provedl jsem
pár pokusů a problém je někde v AJAXu. Když ho vypnu (zakomentuji
načtení nette.ajax.js
), tak to funguje. To jsem si myslel už
v noci, že základni request je bez filtrů, ty přidá až AJAX a nějak
pomocí JS je doplní do adresy, aby fungovall refresh. Ale při tvorbě odkazů
mimo komponentu ty filtry asi nejsou vidět…
- sKopheK
- Člen | 207
Ahoj, mám problém se zpracováváním hromadných operací pro označené
řádky gridu.
Při provádění překreslení přes AJAX se Grid nepřekreslí a jsou v něm
vypsaná stejná data jako před provedením operace. Postupoval jsem stejně
jako v příkladech (kde se však fyzicky žádná operace neprovádí, jen se
zobrazí flash zprávička – to mám v pořádku). Poradíte, jak
refreshovat grid přes AJAX, abych nemusel dělat refresh přes redirect?
- Jan Mikeš
- Člen | 771
Zacinam byt fakt zoufaly, urcite se jedna o nejakou prkotinu a ja to jen prehlizim… Presne podle grido examples zkousim pro Doctrine datasource vypsat sloupec z propojene entity:
$model = new \Grido\DataSources\Doctrine(
$this->entityManager->getDao(Entities\Order::class)->createQueryBuilder('a')
->addSelect('c')
->innerJoin('a.customer', 'c'),
array('firstname' => 'c.firstname'));
$grid->model = $model;
$grid->addColumnText("firstname", "Jméno");
Je to prakticky copypaste primo z examples, nebo delam neco spatne?
Dostavam Kdyby\Doctrine\MemberAccessException
Cannot read an undeclared property
App\Model\Entities\Order::$firstname
// Order.php
/**
* @ORM\OneToOne(targetEntity="Customer", inversedBy="order")
*/
private $customer;
public function setCustomer(Customer $customer)
{
$this->customer = $customer;
$customer->setOrder($this);
return $this;
}
public function getCustomer()
{
return $this->customer;
}
Vazne uz nevim co delam spatne…
Toto mi pro vypis funguje, ale jakmile zacnu pridavat sort/filter/suggestion, pak dostavam ruzne exceptions, takze tusim ze to neni spravny pristup.
$grid->addColumnText("customer.firstname", "Jméno");
Jak tedy spravne pridat sloupec z propojene entity?
- VK
- Člen | 10
Zkus
$model = new \Grido\DataSources\Doctrine(
$this->entityManager
->getRepository(Entities\Order::class)
->createQueryBuilder('a')
->addSelect('c')
->innerJoin('a.customer', 'c'),
[
'customer.firstname' => 'c.firstname'
]
);
$grid->addColumnText("firstname", "Jméno")
->setColumn('customer.firstname');
Včera jsem zrovna dělal něco podobného s translation tabulkami (translatable) a vše funguje.
Editoval VK (13. 3. 2015 10:06)
- kolsi
- Člen | 131
Měl bych jenom takový drobný návrh na vylepšení, které ušetří pár řádků kódu.
Mám kód (pouze schématicky napsáno):
$grid->addActionEvent('delete', 'Delete', function($id) {
if(mám oprávnění smazat položku $id) {
delete $id;
}
})->setDisable(function($item) {
return !(mám oprávnění smazat položku $item->id);
});
A musím tam tu kontrolu oprávnění psát dvakrát. Myslím, že by bylo logičtější, že pokud daný řádek má akci zakázanou (v setDisable), tak by nemělo dojít ani k zavolání callbacku této akce (např. pokud podstrčím ID do URL). Je to jenom drobnost, ale může se hodit :-)
Editoval kolsi (13. 3. 2015 11:14)
- o5
- Člen | 416
kolsi napsal(a):
A musím tam tu kontrolu oprávnění psát dvakrát.
Co takto? :)
$isDeletable = function($id) {
return $id === "XX";
};
$grid->addActionEvent('delete', 'Delete', function($id) use ($isDeletable) {
if($isDeletable($id)) {
delete $id;
}
})->setDisable(function($item) use ($isDeletable) {
return !$isDeletable($item->id);
});
- Jan Mikeš
- Člen | 771
@VK toto funguje, jenze v Doctrine demu je ukazano, ze jako alias muzu pouzit nazev bez nutnosti tecky, netusim v cem je tedy problem, jestli to neni tim, ze v demu existuje property entity „country“ ke ktere se pak vytvari sloupec, ale pouze se ji mapuje hodnota jinam? V tom pripade jde mozna o bug?
edit: anyways diky, muj problem to vyresilo, neni az tak dulezite jestli pisu „customer.firstname“ nebo „firstname“
Editoval Lexi (13. 3. 2015 12:35)