Nextras\Datagrid – datagrid se vsim jak ma byt
- MW
- Člen | 626
Pred tim, nez jsem tam cpal ten svůj $year jsem tam mel
$grid->setDatasourceCallback($this->context->invoicesModel->getDataSource);
$grid->setPagination($this->pag, $this->context->invoicesModel->getDataSourceSum);
Metoda v gridu by se mala postarat o vytvoreni Paginatoru…
public function setPagination($itemsPerPage, $itemsCountCallback = NULL) {
if ($itemsPerPage === FALSE) {
$this->paginator = NULL;
$this->paginatorItemsCountCallback = NULL;
} else {
if ($itemsCountCallback === NULL) {
throw new \InvalidArgumentException('Items count callback must be set.');
}
$this->paginator = new Paginator();
$this->paginator->itemsPerPage = $itemsPerPage;
$this->paginatorItemsCountCallback = new Nette\Callback($itemsCountCallback);
}
}
ted tedy nevim, co tam presne predat na tomhle miste :/
Omlouvam se, asi me unikl nejaky tok.. muzu poprosit to nakopnuti?
Diky!
Editoval MW (30. 8. 2013 13:27)
- jiri.pudil
- Nette Blogger | 1029
Čeho se vůbec snažíš dosáhnout? Neřeší si grid to stránkování
sám právě tou metodou setPagination()
?
- MW
- Člen | 626
Mel by… ale potreboval jsem si pridat parametr $year do komponenty a diky změne na
$_this = $this;
$grid->setDatasourceCallback(function($filter, $order) use ($_this) {
return $_this->context->invoicesModel->getDataSource($filter, $order, $_this->year);
});
a coz nevim jestli dobře, ale pouzil jsem i pro setPagination…
a strankovani razem prestalo fungovat…
Editoval MW (1. 9. 2013 21:53)
- MW
- Člen | 626
Omlouvam se, ale nespina me.. nechapu moc to $_this = $this;
Ted:
Argument 3 passed to IkonisModule\{closure}() must be an instance of Nette\Utils\Paginator, null given
Presenter:
public function createComponentHistory() {
$grid = new \Nextras\Datagrid\Datagrid ();
$grid->addColumn('id');
$grid->addColumn('name')->enableSort();
$grid->addColumn('branches_id', 'Provozovna')->enableSort();
$grid->addColumn('leden', 'Leden');
$grid->addColumn('unor', 'Únor');
......
$_this = $this;
$year = $this->year;
$grid->setDatasourceCallback(function($filter, $order, Paginator $paginator) use ($year) {
return $_this->context->invoicesModel->getDataSource($filter, $order, $paginator, $year);
});
$grid->setFilterFormFactory(function() use ($_this) {
$form = new Nette\Forms\Container;
$form->addText('name');
$form->addSelect('branches_id', 'Provozovna', $_this->context->printersModel->getBranches()->fetchPairs('id', 'name'))->setPrompt('Zvolte');
$form->addSubmit('filter', 'Filtrovat')->getControlPrototype()->class = 'btn btn-primary';
$form->addSubmit('cancel', 'Zrušit filtr')->getControlPrototype()->class = 'btn';
return $form;
});
$grid->addCellsTemplate(LIBS_DIR . '/Addons/Nextras-datagrid/Lattes/history.latte');
return $grid;
}
Model:
public function getData($year) {
return $this->database->table('contracts')->SELECT('id, name, branches_id,
(SELECT SUM(sum) FROM mrp WHERE MONTH(datzdanpln) = 1 AND YEAR(datzdanpln) = '.$year.' AND mrp_cislo = cislo_zak) AS leden,
(SELECT SUM(sum) FROM mrp WHERE MONTH(datzdanpln) = 2 AND YEAR(datzdanpln) = '.$year.' AND mrp_cislo = cislo_zak) AS unor') ...... ;
}
public function prepareDataSource($filter, $order, $year) {
$filters = array();
foreach ($filter as $k => $v) {
if ($k == 'id' || is_array($v))
$filters[$k] = $v;
else
$filters[$k . ' LIKE ?'] = "%$v%";
}
$selection = $this->getData($year)->where($filters);
if ($order[0])
$selection->order(implode(' ', $order));
return $selection;
}
public function getDataSource($filter, $order, $year, Paginator $paginator = NULL) {
$selection = $this->prepareDataSource($filter, $order, $year);
if ($paginator) {
$selection->limit($paginator->getItemsPerPage(), $paginator->getOffset());
}
return $selection;
}
public function getDataSourceSum($filter, $order, $year) {
return $this->prepareDataSource($filter, $order, $year)->count('id');
}
public function saveData($data) {
$data = $data->getValues();
$this->getData()->where('id', $data->id)->update($data);
}
- MW
- Člen | 626
Tak bod 2 se me podařilo vyřešit :
$filters = array();
foreach ($filter as $k => $v) {
if ($k == 'id' || is_array($v))
$filters[$k] = $v;
if ($k == 'name' || is_array($v))
$filters[$k . ' LIKE ? OR desc LIKE ?'] = array("%$v%", "%$v%");
else
$filters[$k . ' LIKE ?'] = "%$v%";
}
Editoval MW (1. 10. 2013 15:41)
- MW
- Člen | 626
Ještě prosím.
Mám v BasePresenteru registrovany helper a a nevim, jak se na něj dostat v sablone gridu.
$this->template->registerHelper('icon', function ($typ) {
switch ($typ) {
case 'image/jpeg' :
$icon = "<img align='left' src='images/icons/image.png'>";
break;
case 'application/pdf' :
$icon = "<img align='left' src='images/icons/pdf.png'>";
break;
case 'application/vnd.ms-excel' :
$icon = "<img align='left' src='images/icons/xls.png'>";
break;
case 'application/msword' :
$icon = "<img align='left' src='images/icons/doc.png'>";
break;
default :
$icon = "<img align='left' src='images/icons/file.png'>";
}
return "$icon";
});
Diky!
- Filip111
- Člen | 244
Ahoj, je nějaká možnost jak si předat do šablony další data kromě
datasetu?
(např. id záznamu na který se chci odkazovat a který nesouvisí přímo
s vypisovanými daty, ale souvisí např. se stránkou na které je grid
umístěn). Potřebuji to kvůli generování odkazů, resp. předávání
parametrů dál.
Z vnějšku si to představuji jako
$grid->template->courseId = $nejakyId;
- Filip111
- Člen | 244
Odpovím si na můj dotaz o 2 posty výš…
Podědil jsem Datagrid, vlastní data ukládám do pole customData, aby nemohlo
dojít ke konfliktu s template daty gridu.
class CustomDatagrid extends Datagrid {
private $customData = null;
public function setCustomData($name, $data) {
if ($this->customData == null)
$this->customData = new ArrayHash;
$this->customData->$name = $data;
}
public function render() {
$this->template->customData = $this->customData;
parent::render();
}
}
Použití:
$grid->setCustomData('courseId', $courseId);
{$customData->courseId}
- David Ďurika
- Člen | 328
MW napsal(a):
hrach napsal(a):
To je zalezitost db vrstvy, jakou pouzivas, ne datagridu, tomu je sumak, co mu davas za data. Jestli nevis jak na sum v nette database, pouzij patricne forum…
Tak jiste, ze sum v db pouzit umim.. myslel jsem nejaky navrh, jak to nejlepe zakomponovat do gridu.
ide o to ze napr na spodku datagridu chces mat este jeden bonusovy riadok v kt. budu SUM vsetkych riadkov a ich hodnout, hej?
v tom pridate ti stacti spravit to ze do tadasource pridas na koniec riadok kde pridas vysledne scitane hodnoty
- MW
- Člen | 626
Pouzivate nekdo hromadne akce ? Planovala se podpora…
A jeste prosim posledni vec.. Udelal jsem si control na vkladani a ja potrebuju aby po ulozeni zustal grid v puvodnim stavu.. Tedy se zachovanim filtru…
Ted se me vzdy hodi vzdy do defaultu. I kdyz jen v presenteru updatnu snipet s gridem.
Diky!
Editoval MW (12. 10. 2013 11:24)
- rixi
- Člen | 109
MW wrote:
hrach napsal(a):
To je zalezitost db vrstvy, jakou pouzivas, ne datagridu, tomu je sumak, co mu davas za data. Jestli nevis jak na sum v nette database, pouzij patricne forum…
Tak jiste, ze sum v db pouzit umim.. myslel jsem nejaky navrh, jak to nejlepe zakomponovat do gridu.
dosiahnut toho ide napriklad rozsirenim triedy Datagrid o metodu
/**
* @return float
*/
public function getPriceSumWithoutTax()
{
return (float) $this->data->sum('total_price_eur');
}
- MW
- Člen | 626
Podedil jsem si teda datagrid a pridal metodu pro soucet:
class OInvoicesGrid extends \Nextras\Datagrid\Datagrid {
public function getTotal() {
return (float) parent::getData()->sum('cena');
}
}
a ted potrebuju to potrebuju poslat do sablony..
Pokud to pridam primo do datagrid.php do render():
$this->template->celkem = $this->getTotal();
Tak to funguje, ja bych ale radsi, kdyby to slo bez upravy datagrid.php a ..
jak na to prosim?
Editaci šablony se asi nevyhnu..
Předem děkuji za rady.
Editoval MW (22. 10. 2013 14:56)
- rixi
- Člen | 109
Tak to funguje, ja bych ale radsi, kdyby to slo bez upravy datagrid.php a .. jak na to prosim?
Editaci šablony se asi nevyhnu..
V triede OInvoicesGrid prepisat metodu render() v ktorej moze byt navyse nieco taketo:
$this->template->celkem = $this->getTotal();
$this->template->setFile(__DIR__ . '/vlastna_datagrid_sablona.latte');
- MW
- Člen | 626
rixi napsal(a):
Tak to funguje, ja bych ale radsi, kdyby to slo bez upravy datagrid.php a .. jak na to prosim?
Editaci šablony se asi nevyhnu..V triede OInvoicesGrid prepisat metodu render() v ktorej moze byt navyse nieco taketo:
$this->template->celkem = $this->getTotal(); $this->template->setFile(__DIR__ . '/vlastna_datagrid_sablona.latte');
Tedy do metody render() dat vse, co je v puvodni v datagrid.php? a vlastní šablona bude zkopirovana puvodni datagrid.latte? Tak to myslis?
Editoval MW (21. 10. 2013 15:31)
- rixi
- Člen | 109
MW wrote:
Tedy do metody render() dat vse, co je v puvodni v datagrid.php? a vlastní šablona bude zkopirovana puvodni datagrid.latte? Tak to myslis?
Ano, lepsie sa mi to nepodarilo, nenapada ma ako. Podedit metodu render() s tym, ze sa tam upravi cesta k suboru. Mozno niekto vie. Ale to je uz trochu OT v teme.
Editoval rixi (22. 10. 2013 15:16)
- sandarina
- Člen | 3
MW napsal(a):
Pouzivate nekdo hromadne akce ? Planovala se podpora…
A jeste prosim posledni vec.. Udelal jsem si control na vkladani a ja potrebuju aby po ulozeni zustal grid v puvodnim stavu.. Tedy se zachovanim filtru…
Ted se me vzdy hodi vzdy do defaultu. I kdyz jen v presenteru updatnu snipet s gridem.
Diky!
Já mám staženou nejnovější DEV verzi z GitHubu a tam hromadná editace řádků funguje. Je to teda tak, že si rozklikneš libovolné množství inline editací. Trošku mi chybí společné ukládací tlačítko, ale určitě jde doprogramovat, jen jsem ještě neměla čas si s tím hrát.
Jinak jsem chtěla poděkovat autorovi gridu. Je fakt super a ušetřil mi mraky času! Doufám, že se komponenta bude dále rozvíjet, moc by se mi líbilo modal okno pro potvrzení DELETE akce nebo možnost přidat class k řádku v inline editaci (aby se dal odlišit).
- juradee
- Člen | 4
juradee napsal(a):
Ahoj, prošel jsem si to tu, ale odpověď jsem nenašel. Existuje nějaká možnost použít inline editaci a zároveň doplnit další akce? Zapsáním akce do {define row-actions} se inline editace smaže (nevypíše se odkaz)
Nenašel jsem žádné elegantnější řešení než překopírovat řádek z datagrid.latte a přidat jej do {define row-actions}
<a href="{link edit! $primary}" class="ajax" data-datagrid-edit>Edit</a>
Asi by se víc líbila možnost dodefinovat akce přímo v továrničce
- MW
- Člen | 626
Toto funguje naprihlad u handleDelete() ale pokud to dam to same, tedy
invalidateControl(‚grid‘), kde je control s gridem do metody formSubmit()
nebo i do saveData() tak me to hodi vždy do vychoziho zobrazeni…
Zkousel jsem vsechno mozne, ale nedokazu docilit toho, abych umistil nad grid formular a po vlozeni zaznamu se refresnul grid se zachovanim filtru a zobrazenim pridaneho zaznamu, pokud je ve filtru obsazen…
Tedy to vidim, ze je rozdil, když to invaliduju v handle nebo v bezne metode??? to je jedine, co me napada…
Diky za rady!
- MW
- Člen | 626
Aby jste me pochopili:
latte:
{snippet formaddInvoices}
{form addInvoice class => 'ajax'}
<ul class="error" n:if="$form->hasErrors()">
<li n:foreach="$form->errors as $error">{$error}</li>
</ul>
<fieldset><legend>Vložit nový</legend>
{label popis /} {input popis} <b>|</b>
{label branches_id /} {input branches_id} <b>|</b>
{label clients_id /} {input clients_id} <b>|</b>
{label cena /} {input cena} <b>|</b>
{label dph /} {input dph} <b>|</b>
{label duzp /} {input duzp} <b>|</b>
{label pozn /} {input pozn} <b>|</b>
{input ulozit}
</fieldset>
{/form addInvoice}
{/snippet}
{snippet grid}
{control oinvoices}
{/snippet}
a presenter:
protected function createComponentAddInvoice($name) {
$form = new Form ($this, $name);
//$form->getElementPrototype()->setClass('ajax');
$form->addText('popis', 'Popis:')->setRequired('Zadejte popis!');
$form->addSelect('branches_id', 'Provozovna', $this->context->oinvoicesModel->getAllBranches()->fetchPairs('id', 'name'))->setPrompt('Zvolte')
->setRequired('Zvolte provozovnu!');
$form->addSelect('clients_id', 'Klient:', $this->context->contractsModel->getClients()->order('name')->fetchPairs('id', 'name'))
->setRequired('Zvolte klienta!')
->setPrompt('')
->setHtmlId('combobox');
$form->addText('cena', 'Cena:')
->getControlPrototype()->style(array("width" => "50px"));
$form->addSelect('dph', 'DPH:', $this->getVat());
$form->addText('mrp_fa', 'Faktura:');
$form->addText('uhrada', 'Úhrada:');
$form->addDatePicker('duzp', 'DUZP:')
->addRule(Form::FILLED, 'Zadejte datum DUZP!')
->getControlPrototype()->style(array("width" => "75px"));;
$form->addText('pozn', 'Poznámka:');
$form->addSubmit('ulozit', "Uložit")
->getControlPrototype()->style(array("background" => 'green', 'color' => "white"));
$form->onSuccess[] = array($this, "addinvoiceSubmit");
}
function addinvoiceSubmit($form) {
$this->saveData($form);
$form->form->setValues(array(), TRUE);
$this->invalidateControl('formaddInvoices');
$this->invalidateControl('grid'); // tady to invaliduje spatne, tedy do výchozího bez zachovani filtru
}
// Grid pro Historii plateb
public function createComponentOinvoices() {
$grid = new OInvoicesGrid ();
$grid->addColumn('id');
$grid->addColumn('popis');
$grid->addColumn('branches_id', 'Provozovna');
$grid->addColumn('clients_id', 'Klient');
$grid->addColumn('cena', 'Cena');
$grid->addColumn('dph', 'DPH');
$grid->addColumn('mrp_fa', 'Faktura č.');
$grid->addColumn('uhrada', 'Uhrazeno');
$grid->addColumn('duzp', 'DUZP');
$grid->addColumn('pozn', 'Poznámka');
$_this = $this;
$grid->setDatasourceCallback(function($filter, $order, Paginator $paginator = null) use ($_this) {
return $_this->context->oinvoicesModel->getDataSource($filter, $order, $_this->year, $paginator);
});
$grid->setPagination($_this->pag, function($filter) use ($_this) {
return $_this->context->oinvoicesModel->getDataSourceSum($filter, $_this->year);
});
$grid->setFilterFormFactory(function() use ($_this) {
$form = new Nette\Forms\Container;
$form->addText('name');
$form->addSelect('branches_id', 'Provozovna', $_this->context->oinvoicesModel->getAllBranches()->fetchPairs('id', 'name'))->setPrompt('Zvolte');
$form->addSelect('uhrada', 'Uhrazeno', array('0' => 'Neuhrazené', '1' => 'Uhrazené'))->setPrompt('')->setPrompt('Vše');
$form->addSelect('duzp', 'DUZP', $_this->getMonths())->setPrompt('Zvolte');
$form->addSubmit('filter', 'Filtrovat')->getControlPrototype()->class = 'btn btn-primary';
$form->addSubmit('cancel', 'Zrušit filtr')->getControlPrototype()->class = 'btn';
return $form;
});
$grid->setEditFormFactory(function($row) use ($_this) {
$form = new Nette\Forms\Container;
$form->addText('popis')->setRequired('Zadat!');
$form->addText('cena');
$form->addSelect('dph', 'DPH:', $_this->getVat());
$form->addText('uhrada');
$form->addSelect('branches_id', 'Provozovna', $_this->context->oinvoicesModel->getAllBranches()->fetchPairs('id', 'name'));
!$row ? : $form->setDefaults($row);
return $form;
});
$grid->setEditFormCallback($this->saveData);
$grid->addCellsTemplate(LIBS_DIR . '/Addons/Nextras-datagrid/Lattes/oinvoices.latte');
return $grid;
}
public function handleDelete($id) {
$this->context->oinvoicesModel->deleteData($id);
$this->invalidateControl('grid'); // tady to invaliduje v poradku se zachovanim filtru.
}
public function saveData($data) {
$this->context->oinvoicesModel->saveData($data);
$this->invalidateControl('grid'); // tady to invaliduje spatne, tedy do výchozího bez zachovani filtru
}
- MW
- Člen | 626
Mam snad poslední zadrzhel.
Potřebuju po inline editaci invalidovat vsechny radky (mam tam sum sloupec a
tedy kvůli prepoctu).
Ovšem po ulozeni inline editace, me to vraci vždy grid s jednim radkem (tim, co jsem editoval.)
presenter:
public function saveData($data) {
$this->context->oinvoicesModel->saveData($data);
$this->invalidateControl('grid');
//$this->redirect('this');
}
invaliduje grid, kde zustane pouze jeden zaznam.
Pokud dam redirect, je to OK.. jen to není ajaxem.
Tady pro jistotu model, nevidíte někdo nejakou koninu, prosim?
model:
class OinvoicesModel extends BaseModel {
//data pro grid
public function getData($year = null) {
If($year) return $this->database->table('vynosyo')->where('YEAR(duzp)', $year);
Else return $this->database->table('vynosyo');
}
public function prepareDataSource($filter, $year, $order = NULL) {
if (!$order) {
$order = array('id DESC');
}
$filters = array();
foreach ($filter as $k => $v) {
if ($k == 'id' || is_array($v))
$filters[$k] = $v;
elseif ($k == 'branches_id' || is_array($v))
$filters[$k] = $v;
elseif ($k == 'uhrada' || is_array($v))
if($v == 1) {$filters[$k . ' > ?'] = 0;}
else {$filters[$k] = 0;}
elseif ($k == 'duzp' || is_array($v))
$filters['MONTH('.$k.')'] = $v;
else
$filters[$k . ' LIKE ?'] = "%$v%";
}
$selection = $this->getData($year)->where($filters);
if ($order[0])
$selection->order(implode(' ', $order));
return $selection;
}
public function getDataSource($filter, $order, $year, Paginator $paginator = NULL) {
$selection = $this->prepareDataSource($filter, $year, $order);
if ($paginator) {
$selection->limit($paginator->getItemsPerPage(), $paginator->getOffset());
}
return $selection;
}
public function getDataSourceSum($filter, $year) {
return $this->prepareDataSource($filter, $year)->count('id');
}
public function saveData($data) {
$data = $data->getValues();
If (!isset($data->id)) {
$this->getData()->insert($data);
} else {
$this->getData()->where('id', $data->id)->update($data);
}
}
Editoval MW (4. 11. 2013 12:55)
- snake.aas
- Člen | 25
Ahoj,
řešil jsem jak zprovoznit filtraci pomocí multiselectu, a nenašel jsem jiné
řešení než změnit řádek
464 v Datagrid.php na
<?php
return (is_array($val) ? count($val) : strlen($val)) > 0;
?>
Uvažuju správným směrem (a mám poslat PR)? Nebo jsem jenom někde tu
možnost mutliselectu přehlédl?
(a nebo ještě jestli tahle úprava nerozbije někde něco jiného, ale
nepřišel jsem na nic)
edit: testováno na @dev verzi
Editoval snake.aas (20. 12. 2013 13:32)
- n.u.r.v.
- Člen | 485
Ahoj, zkouším tento data grid, ale nevím, jak udělat následující:
- mazání položky:
udělal jsem následující tlačítka v @cells.latte:
{define row-actions}
<a href="{link edit! $primary}" class="ttip" title="Přejmenovat" data-placement="right"><i class="fa fa-pencil"></i></a>
<a href="{plink :Admin:Group:delete $primary}" class="ttip" title="Smazat" data-placement="right"><i class="fa fa-trash-o"></i></a>
{/define}
Jenže nevím, jak udělat, abych při mazání předával ještě jeden údaj – momentálně předávám pouze ID, které je jako primary, ale potřeboval bych ještě předat hash, který má každý záznam v DB…Hash v tabulce nikde nevypisuji…
- Potřeboval bych střídat podbarvení řádků tabulky – bez datagridu jsem to dělal takto:
<tr n:foreach="$groups as $list" n:class="$iterator->odd ? odd : even"....
Ale tady nevím, jak to udělat…
- Jak mohu ovlivnit text v tlačítkách pro uložení a editaci?
- Nevím jak do tfood vložit údaj o celkovém počtu záznamů (=řádků)? Potřebuji vložit toto:
<tfoot>
<tr>
<td colspan="3">Počet záznamů: <span>{$groupsCount}</span></td>
</tr>
</tfoot>
Díky
Editoval n.u.r.v. (12. 1. 2014 17:13)
- MartinitCZ
- Člen | 580
Dá se nějak, přidat i sort symbol, když dle daného sloupce není řazeno? Tzv aby tam byl vidět jak ▲, tak ▼.
- hrach
- Člen | 1838
Aktuálně jen předefinováním daného blocku:
{redefine row-head-colums}
<tr class="grid-columns">
{foreach $columns as $column}
<th class="grid-col-{$column->name}">
{if $column->canSort()}
<a href="{link sort! orderColumn => $column->getNewState() ? $column->name : NULL, orderType => $column->getNewState()}" class="ajax">{$column->label}</a>
{if $column->isAsc()}
<span class="grid-sort-symbol"><em>▲</em></span>
{elseif $column->isDesc()}
<span class="grid-sort-symbol"><em>▼</em></span>
{/if}
{else}
{$column->label}
{/if}
</th>
{/foreach}
{if $template->hasActionsColumn}
<th class="grid-col-actions">{ifset #global-actions}{include #global-actions}{/ifset}</th>
{/if}
</tr>
{/redefine}
- hrach
- Člen | 1838
@n.u.r.v.
- v kazdem blocku mas dostupny
$row
, coz je proste ten radek, co se renderuje - doporucuji jen pres css, alternativne si muzes prepsat block
row
, link - bud si tlacitka pridej ve svem editFormFactory (oni se nepridaji znovu,
pokud uz existuji), nebo si prepis block
row-actions-edit
, link - to aktualne nejde, idealne asi by to chtelo PR, ktery zavede tady novy block.
Editoval hrach (12. 1. 2014 18:05)