Odeslání proměnné z formuláře přímo do presenteru

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

Zdravím lidičky,
nette se učím nějaký ten den a tak často narážím na neznalostí bariéry. Rád bych se tedy zeptal.
Vytvářím v presenteru „createComponentUserFilterForm“ – vygeneruje mi to formulář pro vyfiltrování uživatelů podle kraje.

$regionForm = new Form();
	$regionForm->addSelect('region_name_slug', 'Kraj:', $this->getService('database')
		->table('region')->fetchPairs('region_name_slug', 'region_name'))
		->setPrompt('- Vyberte kraj-')
		->addRule(Form::FILLED, 'Pro setřízení dle kraje je nutné vybrat kraj!');
    	$regionForm->addSubmit('filter', 'Filtrovat');
    	$form->onSuccess[] = callback($this, 'renderList'); // jde to posílat přímo do renderListu?
		return $regionForm;

Problém mi vzniká tím, že nejsem schopen si „vycucnout“ hodnotu té proměnné do renderList. Prakticky nevím jak na to. Najde se někdo kdo mi helpne? Můžu to takovým způsobem vůbec dělat? :)

Díky,
A.

frosty22
Člen | 373
+
0
-

Čauky,
no v praxi je zároveň i potřeba (v případě filtru), aby onen filtr měl svou URL adresa (např. kvůli stránkování či posílání URL, apod.)

Zároveň tedy nelze jako callback použít metody „render*, action*, apod., jelikož ty josu volány nettem automaticky v případě nějakých stavů (viz životní cyklus aplikace), čili musíš navěsit jako událost onSuccess nějaký vlastní callback, čili například si vytvořit metodu "processFilterForm“.

<?php
$form->onSuccess[] = callback($this, 'processFilterForm');
?>

A při onom callbacku se předává formulář oné metodě, které ho zpracuje (nyní processFilterForm) a v této metodě tedy můžeš ukládat ony data, a v tomto případě filtrování je předat jako URL (v GETu) na nějakou action, která to bude filtrovat, například:

<?php
public function processFilterForm(Form $form)
{
  // získám obsah formuláře jako pole (= true vrací pole, jinak objekt)
  $values = $form->getValues(true);

  // Přesměrujeme na action "actionList" a předáme obsah formuláře v poli "filter"
  $this->redirect("list", array("filter" => $values));
}
?>

A ona action může být nějak takto:

<?php
public function actionList(array $filter = array())
{
  //$filter obsahuje vždy pole, případě prázdné pokud nejsou data
  $table = $this->context->database->table("table");

  // Filtr například podle toho kraje, pokud je, atp.
  if (isset($filter["region_name_slug"])) $table->where("region_name_slug", $filter["region_name_slug"]);

}
?>
adioverride
Člen | 26
+
0
-

Super, zkoušel jsem jede :) Díky moc, zase jsem o něco chytřejší :D

nanuqcz
Člen | 822
+
0
-

Pak mě napadlo ještě jedno řešení, a to využít životního cyklu presenteru: Že se nejdřív provádí „action“ (zde bych načetl hodnoty z DB), potom „handle“ (zde bych je vyfiltroval podle hodnot z formuláře), a pak „render“ (zde vložil do šablony).

ArticlesPresenter {
	private $articles;

	function actionDefault(){
		$this->articles = $this->context->articlesModel->getArticles();
	}

	function handleProcessForm($form){
		$this->articles->where('category_id', $form->values['category_id']);
	}

	function renderDefault(){
		$this->template->articles = $this->articles;
	}


	function createComponentForm(){
		$form = new Form();
		$form->add...

		$form->onSuccess[] = callback($this, 'handleProcessForm')

		return $form;
	}
}

Výhoda: Stránka se zbytečně nenačítá dvakrát (není použit redirect)
Nevýhoda: Na takto vyfiltrovanou stránku nelze poslat někomu odkaz (hodnoty jsou v POST)

Otázka na ostatní, který způsob je podle vás lepší?

frosty22
Člen | 373
+
0
-

Tak tady snad není potřeba otázek, jaké řešení je lepší – každé má jiné využití.

Tvé řešení pokud se bude jednat o formulář například pro hledání v administraci a omezené skupiny výsledků, kde nebude stránkování, či se nebude jednat o filtr, ale jiný formulář (nenapadá mě příklad).

A řešení, které jsem uvedl já je vhodné pro filtry, kdy jak jsi sám uvedl, tak stránka má přesně definovanou URL, a díky tomu i zároveň je možné např. stránkovat.