kontrola validity formuláře před zavoláním každého onSuccess[]

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

Kdyz pridam do formulare chybu (v ramci jednoho z callbacku v onSuccess[]), tak nechci, aby se zavolal dalsi callback. Mám následující kód a píšu ho tak, protože je to prostě pohodlné :-) :

tovarnicka v Presenteru:

<?php
public function createComponentAddItemForm()
{
	$form = new NAppForm();
	...
	$form->onSuccess[] = callback( $nejakyModel, 'addItem' );
	$form->onSuccess[] = function($form){ ... odeslat potvrzujici email ... };
	return $form;
}
?>

funkce v Modelu:

<?php
public function addItem( $form )
{
	if( duplicate item )
	{
		$form->addError('Duplicate item.');
		return;
	}
	...
}
?>

Upravil jsem si to primo v nette a prijde mi otrava se o to starat pokazde kdyz budu updatovat, proto moje otazka je, jestli je nejaky mene invazivni zpusob jak toho chovani docilit.

Tady je moje uprava:

<?php

class NForm extends NFormContainer
{
	...
	function fireEvents()
	{
		...
		if (isset($valid) || $this->isValid()) {
			//puvodni
			//$this->onSuccess($this);

			//nove
			foreach($this->onSuccess as $callback){
				if($this->isValid()){
					$callback($this);
				}
			}

		} else {
		...
	}
	...
}
?>

Diky

Editoval thool (15. 11. 2011 23:24)

Filip Procházka
Moderator | 4668
+
0
-

Tak první možnost, pro tebe nejjednodušší: Když se podíváš do api, tak si určitě všimneš, že metoda fireEvents() je public. Takže si uděláme abstraktního předka, v něm chování upravíme a pak budeme dědit z upravené třídy

// udělal bych ho abstract, ale ty asi formuláře jako komponenty nepíšeš, co?
class BaseForm extends Nette\Application\UI\Form
{

	/**
	 * Fires submit/click events.
	 * @return void
	 */
	public function fireEvents()
	{
		$submittedBy = $this->isSubmitted();

		if (!$submittedBy) {
			return;

		} elseif ($submittedBy instanceof ISubmitterControl) {
			if (!$submittedBy->getValidationScope() || $this->isValid()) {
				$this->dispatchEvent($submittedBy->onClick, $submittedBy);
				$valid = TRUE;
			} else {
				$this->dispatchEvent($submittedBy->onInvalidClick, $submittedBy);
			}
		}

		if (isset($valid) || $this->isValid()) {
			$this->dispatchEvent($this->onSuccess, $this);
		} else {
			$this->dispatchEvent($this->onError, $this);
		}
	}


	/**
	 * @param array|\Traversable $listeners
	 * @param mixed $arg
	 * @param mixed $arg2
	 * @param mixed $arg3
	 */
	protected function dispatchEvent($listeners, $arg = NULL)
	{
		$args = func_get_args();
		$listeners = array_shift($args);

		foreach ((array)$listeners as $handler) {
			$result = TRUE

			// tohle je bonus, vysvětlím níže
			if ($handler instanceof Nette\Application\UI\Link) {
				$this->getPresenter()->redirectUrl($handler);

			} else {
				$result = callback($handler)->invokeArgs($args);
			}

			if ($result === FALSE) {
				break;
			}
		}
	}

}

Odstranil jsem, pro tebe nepotřebné, chování a přidal ti tam perličku z Kdyby

První věc, nechceš aby se vykonaly další události? Vrátíš FALSE

public function createComponentAddItemForm()
{
        $form = new BaseForm();
        ...
        $form->onSuccess[] = function ($form) { ... ; return FALSE; };
        $form->onSuccess[] = function ($form) { ... nezavolá se ... };
        return $form;
}

A třešnička na konec, když tam dáš

$form->onSuccess[] = $this->lazyLink('this');

Tak se to přesměruje a nemusíš si předávat presenter do události.

thool
Člen | 6
+
0
-

Wow, super! To přesměrování jsem řešil dost krkolomně. Vypadá to skvěle :-)

Díky

thool
Člen | 6
+
0
-

Dalsi generace musim upozornit na detail :-)

Pokud pouzivate flashMessage(), tak spolu s lazyLink nebudou fungovat. Moje stavajici reseni je jine:

$this->onSuccess[] = function( $form ) use ( $presenter ) {
	if( ... model hlasi uspech ... ) {
		flash message
	}
	$presenter->redirect('this');
};

a to prave kvuli zpravickam ktere se pri pouziti lazyLink nezobrazuji

Filip Procházka
Moderator | 4668
+
0
-

Díky za upozornění, v Kdyby jsem si to opravil, ale pull posílat nebudu. Mám takové tušení, že Davidovi by se takové chování nelíbilo a doporučil by použití closury.