Závislost tvorby formuláře na jejím uložení při ajaxu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
thirdknown
Člen | 26
+
0
-

Ahoj,
mám v presenteru ajaxový formulář generovaný pomocí createComponentSomeForm. V něm mám tlačítko submit s caption „Provést něco“.

Stisknu-li submit, je zavolán ajaxový požadavek a v něm onSuccess handler, v kterém provedu nějakou „akci“ (logika+DB) a nechám překreslit snippet formuláře, protože v createComponentSomeForm si volím caption pro submit – v DB se ptám, zda byla „akce“ už provedena (jestli to je v DB). Pokud ano, caption bude „Provést něco znovu“.

Jenže – i když je v DB akce uložena tím handlerem, snippet formuláře se překreslí pouze s caption „Provést něco“, ne „Provést něco znovu“.
Chápu životní cyklus presenteru. Startup, action, signal (což je i zpracování formuláře), render, createComponentSomeForm. Jenže když odešlu formulář, createComponentSomeForm není volán až s render, ale už při prvním použití SomeForm, tedy signálu zpracování formuláře. Tím pádem se mi zavolá vytvoření formuláře se starým caption („Provést něco“) ještě před uložením do DB v signal form handleru.

Moje otázka zní: lze nějak hezky zpracovat formulář ještě před voláním createComponentSomeForm, nebo si musím opravdu na prasáka třeba v action odlovit $_POST nebo request a uložit do DB, aby si createComponentSomeForm už načetla z DB nové hodnoty, tím pádem vytvořila submit s tlačítkem „Provést něco znovu“?

Stránku mám v bootstrap modalu, takže ajax chci používat kvůli tomu, abych nemusel v presenteru ve form handleru používat redirect, čímž by prohlížeč dostal http redirect a tím bych si v důsledku shodil v prohlížeči modal.

Díky!

Editoval thirdknown (7. 4. 2017 23:14)

David Matějka
Moderator | 6445
+
0
-

ukaz kod

Tyraxor
Člen | 31
+
-1
-

Ahoj,
abys mohl formulář zpracovat, tak ho musíš nejdřív vytvořit, jinak nevíš co máš zpracovávat, tedy volani „createComponentSomeForm“, ale teoreticky by mělo by jít po zpracování formuláře ho znovu vytvořit a tím ho naplnit správnýma hodnotama.
Zkus dat po zpracovaní formuláře něco jako:

<?php
$this['someForm'] = $this->createComponentSomeForm();
?>

Editoval Tyraxor (8. 4. 2017 9:19)

thirdknown
Člen | 26
+
0
-

@Tyraxor Nejsem si jistý jestli se voláním {control someForm} nevezme už vytvořený formulář. Mohl bych to zkusit.

thirdknown
Člen | 26
+
0
-

Kód (napsal jsem zjednodušený příklad mého kódu, aby bylo vše viditelné):

<?php

namespace App\Presenters;

use Nette;
use Nette\Application\UI\Form;

class ArticlePresenter extends Nette\Application\UI\Presenter
{

	/** @var  Nette\Database\Context @inject */
	public $dbContext;

	private $idDetail;


	public function actionDetail($id)
	{
		$this->idDetail = $id;
	}


	public function renderDetail($id)
	{
		$this->template->countSends = $this->countSends($id);
	}


	public function createComponentSomeForm()
	{
		$form = new Form();

		$form->getElementPrototype()->class = 'ajax';

		$form->addText('message', 'Zpráva')
			->setRequired('Vyplňte zprávu');

		if ($this->existsAtLeastOneSend($this->idDetail)) {
			$submitCaption = 'Odeslat znovu';
		} else {
			$submitCaption = 'Odeslat poprvé';
		}

		$form->addSubmit('submit', $submitCaption);

		$form->onSuccess[] = [$this, 'processSomeForm'];

		return $form;
	}


	public function processSomeForm(Form $form, $values)
	{

		$this->registerSend($this->idDetail, $values['message']);

		$this->flashMessage('Odeslání bylo úspěšné');

		if ($this->isAjax()) {
			$this->redrawControl('someForm');
			$this->redrawControl('countSends');
			$this->redrawControl('flashes');
		} else {
			$this->redirect('this');
		}

	}


	public function registerSend($idArticle, $message)
	{
		$this->dbContext->table('article_sends')->insert([
			'id_article' => $idArticle,
			'message' => $message,
		]);
	}


	public function existsAtLeastOneSend($idArticle)
	{
		return (bool) $this->countSends($idArticle);
	}


	public function countSends($idArticle)
	{
		return $this->dbContext->table('article_sends')->where([
			'id_article' => $idArticle,
		])->count();
	}


}

View:

{block content}

{snippet countSends}
	Počet odeslání: {$countSends}
{/snippet}

{snippet someForm}
	{control someForm}
{/snippet}
thirdknown
Člen | 26
+
+1
-

Myslím, že jsem problém vyřešil tak, že submit caption generuji až v latte.
Změny:

public function renderDetail($id)
	{
		$this->template->idArticle = $id;
		$this->template->countSends = $this->countSends($id);
	}


	public function createComponentSomeForm()
	{
		$form = new Form();

		$form->getElementPrototype()->class = 'ajax';

		$form->addText('message', 'Zpráva')
			->setRequired('Vyplňte zprávu');

		$form->addSubmit('submit');

		$form->onSuccess[] = [$this, 'processSomeForm'];

		return $form;
	}

View:

{block content}

{snippet countSends}
	Počet odeslání: {$countSends}
{/snippet}

{snippet someForm}
	{form someForm}
		{input message}

		{if $presenter->existsAtLeastOneSend($idArticle)}
			{var $submitCation = 'Odeslat znovu'}
		{else}
			{var $submitCation = 'Odeslat poprvé'}
		{/if}

		<input n:name="submit" value="{$submitCation}">
	{/form}
{/snippet}

Třeba to někomu pomůže.

David Matějka
Moderator | 6445
+
+1
-

taky bys to mohl vyresit tak, ze po zpracovani formulare zmenis caption:

$this->registerSend($this->idDetail, $values['message']);
$form['submit']->caption = 'Odeslat znovu';
thirdknown
Člen | 26
+
0
-

Díky moc!