kontrola validity formuláře před zavoláním každého onSuccess[]
- thool
- Člen | 6
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
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
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
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.