Předání hodnoty do komponenty – Ajax

aha009
Člen | 50
+
0
-

Ahoj, potřeboval bych poradit jak předat změněnou hodnotu (datum) Ajaxem.
Po kliknutí na odkaz se mi datum změní, ale když odešlu formulář, tak v processForm mám původní hodnotu a ne tu, kterou chci nastavit přes handleDate($date). Děkuji

Presenter

final class DietOrderPresenter extends BasePresenter
{
    /** @var string */
    private $date;

    public function actionDefault(): void
    {

        $date = new DateTime();
        $this->date = $date->format('Y-m-d');

    protected function createComponentDietOrderForm()
    {
        $form = $this->dietOrderFormFactory->create($this->date);
        $form->onSuccess[] = function (UI\Form $form) {
            $this->redrawControl();
        };
        return $form;
    }

    public function handleDate($date)
    {
        $this->date = $date;
        if (($this->isAjax())) {

Form

class DietOrderFormFactory extends UI\Control
{
    /** @var string */
    private $date;


    public function create($date)
    {
        $this->date = $date;
        $form = new UI\Form();
        $form->onSuccess[] = [$this, 'processForm'];
        return $form;
	}

    public function processForm($form, $values)
    {
		bdump($this->date);
	}
Polki
Člen | 553
+
+1
-

Takto to neuděláš.
Jelikož každý request je samostatný, tak sena každý request pohlíží jako na unikát.

Tedy v každém requestu se provede nejdřív action, pak handle, pak render atd..

V tvém případě při prvním vykreslování stránky se nastaví v action metodě datum na nové (btw. lepší je použít Nette\Utils\DateTime takto: DateTime::from(‚now‘)->format(‚Y-m-d‘)).
Pak se vykreslí formulář a hotovo.

Potom někdo spustí událost přenastavení data: Spustí se presenter, opět se provede action metoda, která datum nastaví na teď, pak se provede handle, který datum přenastaví na to, co vybral uživatel, pak se vykreslí formulář a hotovo.

Potom ten stejný člověk odešle formulář: Spustí se presenter, provede se action metoda, která nastaví datum na aktuální a pak se vytvoří formulář a zavolá jeho metoda processForm (Callbacky formuláře se chovají jako handle metody.) Jenže jak vidíš, tak se opět provedla action metoda, která nastavila datum na aktuální. (Kdyby si v ní datum nenastavil vůbec, stejně by bylo null, protože to, že se provedl handle v minulém requestu na to nemá vliv. Ten minulý request se změnou data se sice provedl, ale pak se to zahodilo.)

Řešení je třeba takové:

final class DietOrderPresenter extends BasePresenter
{
	#[Nette\Application\Attributes\Persistent]
	public string $date = '';

	public function actionDefault(): void
	{
		if (!$this->date) {
			$this->date = Nette\Utils\DateTime::from('now')->format('Y-m-d');
		}
	}

	protected function createComponentDietOrderForm(): Nette\Application\UI\Control
	{
		$form = $this->dietOrderFormFactory->create($this->date);
		$form->onSuccess[] = function (UI\Form $form) {
			$this->redrawControl();
		};
		return $form;
	}

	public function handleDate(string $date): void
	{
		$this->date = $date;
	}
}

Čímž jsi udělal z řetězce datumu persistentní parametr předávaný v URL, takže jej budeš mít. Důležité je ale provést ještě validaci, jestli jde opravdu o datum (uživatel může podvrhnout svůj libovolný řetězec) a dát si pozor, aby se v té URL opravdu posílal (Například při ajax requestech, aby se měnila URL.)

Alternativně můžeš využít jakékoliv dočasné úložiště dat. Jen prosím s rozumem.

aha009
Člen | 50
+
0
-

Díky za vysvětlení. Už mi to funguje.