DI zavislot ve factory $this ->isAjax()

turbo80
Člen | 50
+
0
-

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 | 656
+
0
-

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
+
0
-

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 | 656
+
0
-

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
+
0
-

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)

Martk
Člen | 656
+
0
-

Proměnná $this->afterAction nebude validní callback, vsadím se, že je null namísto předávaného closure

turbo80
Člen | 50
+
0
-

Martk napsal(a):

Proměnná $this->afterAction nebude validní callback, vsadím se, že je null namísto předávaného closure

je pravda ze jsem ji definoval private ajako string nic vic

turbo80
Člen | 50
+
0
-

Ja uz nevim jak na to internet je mocny, ale zadnou radu jsem nenasel. Moc dekuji za dalsi rady…

David Matějka
Moderator | 6445
+
0
-

@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
+
0
-

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
+
0
-

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();
}
David Matějka
Moderator | 6445
+
0
-

a nebo si ten onChange callback muzes nastavit v presenteru