Flash zprávy a vícenásobné použití formulářů

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

Tvořim formuláře pomocí techniky která je zde a potřebuju mít metodu proccess pro každý formulář v třidě a zároveň používat flash zprávy v presenteru. Je nějak možné informovat o úspěchu nebo neůspěchu provedení metody process flash zprávou, ikdyž není funkce process v presenteru?

Jan Endel
Člen | 1016
+
0
-

Nejideálněji k tomu přistoupíš asi tak, že celý formulář obalíš komponentou, která sama o sobě umí s flash zprávami pracovat.

Nutelac
Člen | 58
+
0
-

Takže mám formulář dědit od nette\application\ui\control?

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Úplně je nejlepší je dědit od čehokoliv, ale UI reakci (redirect, flashMessage…) řešit na odpovídající úrovni. Tzn. ve svém formuláři si přidat tzv. událost (public $onSomething), do ní v továrničce v presenteru zaregistrovat nějakou metodu presenteru, a v ní volat flashMessage, kde je tato metoda normálně dostupná.

Případně ano, lze dědit od UI\Control, který potřebnými metodami disponuje taky.

vvoody
Člen | 910
+
0
-

Takze zhruba takto?

Davidova slzbotovarnicka

class CreateOrEditUserFormFactory extends Nette\Object
{
        private $db;

        public function __construct(Nette\Database\Connection $db)
        {
                $this->db = $db;
        }

        public function createForm($userId)
        {
                return new CreateOrEditUserForm($this->db);
        }

}

Komponenta s formularom

class CreateOrEditUserForm extends Nette\Application\UI\Control
{
        private $db;

        public function __construct(Nette\Database\Connection $db)
        {
                $this->db = $db;
        }

        public function createComponentForm($userId)
        {
                $form = new Form;
                ...
                $form->addHidden('userId', $userId);
                $form->addSubmit('send', 'Update Account');
                $form->addSubmit('sendandview', 'Update Account and continue editing')
                        ->onClick[] = $this->process;
                return $form;
        }

        public function process($button)
        {
                ...
        }

	public function render(){
		$template = $this->template;
    		$template->setFile(dirname(__FILE__) . '/CreateOrEditUserForm.latte');
    		$template->render();
	}
}

CreateOrEditUserForm.latte

{control Form}

alebo

{form Form}
...
{/form}

Edit: to je asi volovia, teraz sa z toho vytratila ta znovupouzitelnost

Editoval vvoody (9. 9. 2012 22:15)

22
Člen | 1478
+
0
-

a toto je co?

...
public function createComponentForm($userId)
...

@vojtech.dobes: Jinak asi bych so vytvořil potomky Form\Container a v UI\Control to seskládal nebo klasicky podědit UI\Form do nějakeho BaseForm a pak jen v případě potřeby manuálního renderu to obalit UI\Control.

Editoval 22 (9. 9. 2012 23:05)

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Pozor, je to hrozně témat, co se míchá dohromady :). Dědit od Nette\Forms\Form nebo Nette\Forms\Container nepomůže, protože ty nemají metody flashMessage atd., což je issue tohoto vlákna.

Editoval vojtech.dobes (9. 9. 2012 23:07)

22
Člen | 1478
+
0
-

@vojtěch.dobeš: já ale navrhoval dědit od UI\Form, ten má getPresenter() a pak se už k flashMessage dostaneš nebo pro manuál render, vytvořit UI\Control obálku, ať už jsou to Form\Containery nebo extendnuté UI\Form. Form\Container mi přijde vhodný kvůli znovupoužitelnosti a je jedno, jestli to ve finále seskládš v UI\Form nebo UI\Control extendované třídě, záleží na způsobu renderu už jen potom.

Pan Dobrman
Člen | 45
+
0
-

Mě napadlo něco takového.

FormFactory:

<?php

use Nette\Application\UI\Form

class FormFactory
{
	/** @var Model\Model */
	private $model;

	public function createForm()
	{
		$form = new Form;
		$form->addText('text');
		$form->addSubmit('submit');
		//žádný onSuccess
		return $form;
	}

	public function process(Form $form)
	{
		$this->model->save($form); //v případě neúspěchu vyhodí výjimku
	}
}

Presenter:

<?php

use Nette\Application\UI\Form

class FormPresenter extends BasePresenter
{
	/** @var FormFactory */
	private $formFactory;

	public function actionForm()
	{
		$form = $this->formFactory->createForm();
		$form->onSuccess[] = callback($this, 'processForm');
		$this->addComponent($form, 'form');
	}

	public function processForm(Form $form)
	{
		try
		{
			$this->formFactory->process($form);
			$this->flashMessage('Formulář byl odeslán', 'success');
		}
		catch(\Exception $e)
		{
			$this->flashMessage('Formulář se nepodařilo se odeslat', 'error');
		}
	}

	public function injectFormFactory(FormFactory $formFactory)
	{
		$this->formFactory = $formFactory;
	}
}

Je to možné použít?

Editoval Pan Dobrman (15. 9. 2012 15:52)

Patrik Votoček
Člen | 2221
+
0
-

Pan Dobrman napsal(a):

Mě napadlo něco takového.

Já bych na to šel asi takhle:

FormFactory:

use Nette\Application\UI\Form

class FormFactory extends \Nette\Object
{
	/** @var Model\Model */
	private $model;

	public function createForm()
	{
		$form = new Form;
		$form->addText('text');

		$form->addSubmit('submit');

		$from->onSuccess[] = callback($this, 'process');

		return $form;
	}

	public function process(Form $form)
	{
		try {
			$this->model->save($form); //v případě neúspěchu vyhodí výjimku
		} catch (ModelException $e) {
			$this->addError($e->getMessage());
		}
	}
}

Presenter:

<?php

use Nette\Application\UI\Form

class FormPresenter extends BasePresenter
{
	/** @var FormFactory */
	private $formFactory;

	public function createComponentMyForm()
	{
		$presenter = $this;
		$form = $this->formFactory->createForm();
		$form->onSuccess[] = function($form) {
			if ($form->valid) {
				$presenter->flashMessage('Fuk Yea!');
				$presenter->redirect('this');
			}
		}
		return $form;
	}

	public function injectFormFactory(FormFactory $formFactory)
	{
		$this->formFactory = $formFactory;
	}
}
Pan Dobrman
Člen | 45
+
0
-

Téma bylo o odesílání flashMessage, takže proto jsem odchytával výjimky až v presenteru. V továrničce je lze odesílat (alespoň co vím) jen pomocí dědění například od Nette\Application\UI\Control. V tom mi mé řešení přijde hezčí, ale budu rád opraven, pokud se mýlím.

Editoval Pan Dobrman (15. 9. 2012 17:33)