Pořadí callbacků Click a onValidate

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

Ve formuláři mám více submitů. Jeden uloží data o uživateli do databáze, druhý submit by měl celý formulář „zahodit“ a do databáze uložit nějaké defaultní hodnoty. Kód vypadá takto:

<?php

class CreateOrEditUserForm extends Form {

	public function __construct($DI) {
		parent::__construct();

		//...

		$this->addSubmit('send', $t->_('Update Account'));
		$this->addSubmit('sendandview', $t->_('Update Account and continue editing'))
			->onClick[] = callback($this, 'redirectSelf');
		$this->addSubmit('cancel', $t->_('Cancel and drop changes'))
			->onClick[] = callback($this, 'cancel');

		//...

	}

}

?>

Továrnička v presenteru pak vypadá takto:

<?php

	protected function createComponentCreateOrEditUserForm() {

		$DI = new \Nette\DI\Container();
		$DI->addService('translator', $this->translator);
		$DI->addService('connection', $this->context->database);
		$DI->parameters['supported_languages'] = $this->context->parameters['supported_languages'];
		$DI->parameters['userid'] = isset($this->params['userid']) ? $this->params['userid'] : null;
		$component = new CreateOrEditUserForm($DI);

		$component->onValidate[] = callback($component, 'validateForm');
		$component->onSuccess[] = callback($component, 'formSubmit');
		return $component;

	}

?>

Potíž nastane ve chvíli, kdy kliknu na tlačítko ‚Cancel and drop changes‘. Před callbackem CreateOrEditUserForm::cancel se totiž volá CreateOrEditUserForm::validateForm. V případě, že do formuláře napíšu nesmysly mi to místo provedení „cancel“ vrátí formulář s chybami. Jak z toho ven? Lze nějak zařídit, aby se validace volala až po clicku?

Editoval thunderbuff (21. 8. 2012 17:41)

thunderbuff
Člen | 164
+
0
-

Nakonec jsem se vzdal callbacku, vyřešeno pomocí:

<?php

$form['cancel']->isSubmittedBy()

?>
Tomáš Votruba
Moderator | 1114
+
0
-

Přijde mi divné dávat DI container do továrničky na formulář, ale snad máš své důvody. Pokud ne, zkus stejný výsledek dosáhnout v sandboxu, kde to půjde o poznání lépe.

Jen jsem chtěl podotknout, že formuláři stačí předat translator a o překlad už se postará.

castamir
Člen | 629
+
0
-
$form["cancel"]->setValidationScope(FALSE);

Editoval castamir (22. 8. 2012 4:29)

thunderbuff
Člen | 164
+
0
-

@castamir: díky!

Schmutzka napsal(a):

Přijde mi divné dávat DI container do továrničky na formulář, ale snad máš své důvody. Pokud ne, zkus stejný výsledek dosáhnout v sandboxu, kde to půjde o poznání lépe.

Žádné zvláštní důvody nemám, jen mi to přišlo praktické. Co přesně myslíš formulací „Pokud ne, zkus stejný výsledek dosáhnout v sandboxu“?

Editoval thunderbuff (21. 8. 2012 23:30)

Filip Procházka
Moderator | 4668
+
0
-

Opravu je to hrozné :) Ukážu ti jak to udělat lépe.

Nejprve upravíš formulář, aby přijímal konstruktorem konkrétní služby, nikoliv celý DIC

class CreateOrEditUserForm extends Form
{
        public function __construct(Nette\Database\Connection $db)
	{
		parent::__construct()
		// ..

		$this->addSubmit('send', 'Update Account');
                $this->addSubmit('sendandview', 'Update Account and continue editing')
                        ->onClick[] = callback($this, 'redirectSelf');
                $this->addSubmit('cancel', 'Cancel and drop changes')
                        ->onClick[] = callback($this, 'cancel');

		// ...
	}

	public function setSupportedLanguages($langs)
	{
		// předpokládám, že tohle nastavuješ nějakému formulářovému prvku
		$this['supported_languages']->setDefaultValue($langs);
	}

	public function setUserId($userId)
	{
		$this['userId']->setDefault($userId);
	}
}

Potom si nadefinuješ továrničku v DIC

factories:
	userSettingsForm:
		class: CreateOrEditUserForm # databáze bude předána automaticky
		setup:
			- setTranslator() # translator bude předán automaticky
			- setSupportedLanguages(%supported_languages%)

A potom ji použiješ

protected function createComponentCreateOrEditUserForm()
	{
		// vytvoří se formulář
		// automaticky se předá databáze, translator a podporované jazyky
        $form = $this->context->createUserSettingsForm();

		// aktuální přihlášený uživatel
		$form->setUserId($this->user->id);

        $form->onValidate[] = callback($form, 'validateForm');
        $form->onSuccess[] = callback($form, 'formSubmit');

        return $form;

}

Takhle to vypadá lépe ne? ;) Bez magie.

Editoval HosipLan (22. 8. 2012 9:38)

David Grudl
Nette Core | 8218
+
0
-

Úplně bez magie to není, stále tam straší context. Řešil bych to spíš takto.