DI zavislot ve factory $this ->isAjax()
- turbo80
- Člen | 50
Ahoj,
potreboval bych poradit s touto chybou „Call to undefined method …ArticleMenuGridFactory::isAjax()“. Je mi jasne, ze mi chyby zavislost. nemuzu prijit jak to napsat aby to fungovalo jak ma. Vsem predem dekuji. Mam tento kod.
Spolecna factory DatagridFactory:
<?php
use Nette\Database\Context;
use Ublaboo\DataGrid\DataGrid;
use Ublaboo\DataGrid\Localization\SimpleTranslator;
abstract class DatagridFactory
{
/** @var string */
protected $table;
/** @var Context */
public $database;
function __construct(Context $database)
{
$this->database = $database;
}
public function create($id)
{
$grid = new DataGrid;
$grid->setDataSource($this->getSelection($id));
$this->setupGrid($grid);
$translator = new SimpleTranslator([
'ublaboo_datagrid.no_item_found_reset' => 'Žádné položky nenalezeny. Filtr můžete vynulovat',
'ublaboo_datagrid.no_item_found' => 'Žádné položky nenalezeny.',
'ublaboo_datagrid.here' => 'zde',
'ublaboo_datagrid.items' => 'Položky',
'ublaboo_datagrid.all' => 'všechny',
'ublaboo_datagrid.from' => 'z',
'ublaboo_datagrid.reset_filter' => 'Resetovat filtr',
'ublaboo_datagrid.group_actions' => 'Hromadné akce',
'ublaboo_datagrid.show_all_columns' => 'Zobrazit všechny sloupce',
'ublaboo_datagrid.hide_column' => 'Skrýt sloupec',
'ublaboo_datagrid.action' => 'Akce',
'ublaboo_datagrid.previous' => 'Předchozí',
'ublaboo_datagrid.next' => 'Další',
'ublaboo_datagrid.choose' => 'Vyberte',
'ublaboo_datagrid.execute' => 'Provést',
]);
$grid->setTranslator($translator);
$grid->setRefreshUrl(false);
return $grid;
}
abstract protected function setupGrid(DataGrid $grid);
protected function getSelection($id)
{
return $this->database->table($this->table)->where('idParent',$id);
}
protected function getSelection2()
{
return $this->database->table($this->table);
}
}
?>
ArticleMenuGridFactory.php
<?php
use Ublaboo\DataGrid\DataGrid;
class ArticleMenuGridFactory extends DatagridFactory
{
/** @var string */
protected $table = 'menu_article';
protected function setupGrid(DataGrid $grid)
{
$grid->addColumnNumber('poradi', 'Pořadí zobrazení');
$grid->addColumnText('name', 'Název menu');
$grid->addColumnLink('link', 'Typ menu / Vstup do editace článků a podmenu', 'menu');
$grid->addColumnStatus('active', 'Status')
->setCaret(FALSE)
->addOption(1, 'ano')
->setIcon('check')
->setClass('btn-success ajax')
->endOption()
->addOption(0, 'ne')
->setIcon('close')
->setClass('btn-danger ajax')
->endOption()
->onChange[] = [$this, 'statusChange'];;
}
public function statusChange($id, $new_status)
{
$this->getSelection2()->where('id',$id)->update(['active' => $new_status]);
if($this->isAjax())/*zde je chyba*/
{
}
}
}
?>
chyba je v ArticleMenuGridFactory → statusChange
v presenteru
<?php
protected function createComponentMenuPage(string $name): DataGrid
{
return $this->ArticleMenuGridFactory->create($this->id);
}
?>
Vsem dekuji za pripadne rady
- Martk
- Člen | 661
Jestli je ajax request se v prezenteru zjišťuje takto: https://github.com/…resenter.php#…
, takže by mělo stačit injektnout Nette\Http\IRequest
Edit: Jestli chceš přepisovat snippety, tak to doporučuji až v presenteru:
protected function createComponentMenuPage(string $name): DataGrid
{
return $this->ArticleMenuGridFactory->create($this->id, function () {
if ($this->isAjax()) {
$this->redrawControl('snippet');
}
});
}
public function statusChange($id, $new_status)
{
$this->getSelection2()->where('id',$id)->update(['active' => $new_status]);
($this->afterAction)();
}
Editoval Martk (2. 7. 2020 13:10)
- turbo80
- Člen | 50
Martk napsal(a):
Jestli je ajax request se v prezenteru zjišťuje takto: https://github.com/…resenter.php#… , takže by mělo stačit injektnout
Nette\Http\IRequest
Edit: Jestli chceš přepisovat snippety, tak to doporučuji až v presenteru:
protected function createComponentMenuPage(string $name): DataGrid { return $this->ArticleMenuGridFactory->create($this->id, function () { if ($this->isAjax()) { $this->redrawControl('snippet'); } }); }
public function statusChange($id, $new_status) { $this->getSelection2()->where('id',$id)->update(['active' => $new_status]); ($this->afterAction)(); }
Potrebuji rozeznat jak fce byla pouzita treba u statusChange bude $this[‚menuPage‘]->redrawItem($id); aby se me provedl spravnej pozadavek. jestli mi rozumis
- Martk
- Člen | 661
Třeba takto, konstanta není potřeba, když to použiješ jen u této metody
event:
class AfterActionEvent
{
private const STATUS_CHANGE_TYPE = 'statusChange';
/** @var string */
private $type;
/** @var array */
private $arguments;
public function __construct(string $type, array $arguments = [])
{
$this->type = $type;
$this->arguments = $arguments;
}
public function isType(string $type): bool
{
return $this->type === $type;
}
public function getArgument(string $name)
{
if (!isset($this->arguments[$name])) {
throw new InvalidArgumentException("Argument $name does not exist");
}
return $this->arguments[$name];
}
}
public function statusChange($id, $new_status)
{
$this->getSelection2()->where('id',$id)->update(['active' => $new_status]);
($this->afterAction)(new AfterActionEvent(AfterActionEvent::STATUS_CHANGE_TYPE, ['id' => $id]));
}
protected function createComponentMenuPage(string $name): DataGrid
{
return $this->ArticleMenuGridFactory->create($this->id, function (AfterActionEvent $event) {
if ($this->isAjax() && $event->isType(AfterActionEvent::STATUS_CHANGE_TYPE)) {
$this->redrawControl($event->getArgument('id'));
}
});
}
Jde to čistějším způsobem, ale na mě to je teď moc psaní.
Editoval Martk (2. 7. 2020 14:27)
- turbo80
- Člen | 50
Martk napsal(a):
Třeba takto, konstanta není potřeba, když to použiješ jen u této metody
event:
class AfterActionEvent { private const STATUS_CHANGE_TYPE = 'statusChange'; /** @var string */ private $type; /** @var array */ private $arguments; public function __construct(string $type, array $arguments = []) { $this->type = $type; $this->arguments = $arguments; } public function isType(string $type): bool { return $this->type === $type; } public function getArgument(string $name) { if (!isset($this->arguments[$name])) { throw new InvalidArgumentException("Argument $name does not exist"); } return $this->arguments[$name]; } }
public function statusChange($id, $new_status) { $this->getSelection2()->where('id',$id)->update(['active' => $new_status]); ($this->afterAction)(new AfterActionEvent(AfterActionEvent::STATUS_CHANGE_TYPE, ['id' => $id])); }
protected function createComponentMenuPage(string $name): DataGrid { return $this->ArticleMenuGridFactory->create($this->id, function (AfterActionEvent $event) { if ($this->isAjax() && $event->isType(AfterActionEvent::STATUS_CHANGE_TYPE)) { $this->redrawControl($event->getArgument('id')); } }); }
Jde to čistějším způsobem, ale na mě to je teď moc psaní.
<?php
public function statusChange($id, $new_status)
{
$this->getSelection2()->where('id',$id)->update(['active' => $new_status]);
($this->afterAction)(new AfterActionEvent(AfterActionEvent::STATUS_CHANGE_TYPE, ['id' => $id]));
}
?>
upravil jsem dle tvych rad a chyba, ale nechapu kde.
<?php
/** @var string*/
private $afterAction;
.
.
($this->afterAction)(new AfterActionEvent(AfterActionEvent::STATUS_CHANGE_TYPE, ['id' => $id]));/*chyba*/
?>
a hlasi me to chybu Function name must be a string
Editoval turbo80 (2. 7. 2020 15:45)
- David Matějka
- Moderator | 6445
@turbo80 Martk se te snazil navest, abys do afterAction ulozil ten callback, ktery se posila z presenteru. za me je lepsi reseni nepouzivat tu property a udrzet si factory bezstavovovu (muze to zpusobit problemy) a provest to zhruba takhle
- turbo80
- Člen | 50
David Matějka napsal(a):
@turbo80 Martk se te snazil navest, abys do afterAction ulozil ten callback, ktery se posila z presenteru. za me je lepsi reseni nepouzivat tu property a udrzet si factory bezstavovovu (muze to zpusobit problemy) a provest to zhruba takhle
@DavidMatějka @Martk
Ja vim, ze se me Martk snazil navest, ale nejsou mi jasne callbacky. nejak navim
jak na ne poslal jsi mi odkaz s radou a opet nevim jak to pouzit. Opat callback
$saveCallback($id); jestli to je pak fce.
<?php
function $saveCallback($id)
{
a tady treba ulozeni do db nebo
$this->redrawControl
}
?>
doted jsem tovarny nepouzival vse jsem mel v presneterech a tam to vse fungovalo, ale v nekterych presenetrech toho je uz hodne a hlavne to zacina byt hodne neprehledne. U formularu mi vse funguje jak ma co potrebuji, ale datagridu prave ze ne.
- David Matějka
- Moderator | 6445
1. do promenne si muzes ulozit closure, v presenteru tak treba muzes zapsat
$doSomething = function () {
if ($this->isAjax()) {
...
}
}
2. tuhle funkci si muzes poslat do tovarny.
treba tvoje tovarna na grid prijima id, tak bude prijimat i callback
public function create($id, $someCallback)
{
a v createComponent nejaky ten callback predas
a v kdekoliv ten callback muzes zavolat
$someCallback();
nebo si do nej predat argumenty
$someCallback($id)
3. a muzes ho vyuzit v nejakym callbacku komponenty, treba
$grid->onChange[] = function () use ($someCallback) {
...
$someCallback();
}