V componentě generuju form a někde se mi ztrácí parametr

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

Components.php
UsermainPresenter.php
default.phtml

Problém je někde na těchto řádcích.

Jde o to, že po odeslání formuláře (který se vykreslí v pořádku nedojde k odeslání čehokoliv co bylo vytvořeno pomocí proměnné $rIds… Tedy zřejmě ten parametr posílám někde ve špatný čas.

Procházel jsem fóra křížem krážem, ale už z toho mám velkou hlavu a kdyby to šlo hrubou silou (kladivem atd.) tak už jsem to tak dávno udělal =D

Díky za jakoukoliv radu. Vycházel jsem z tohoto příspěvku

westrem
Člen | 398
+
0
-

Problem je jasny.

Tento riadok:

{control requestsForm, 'adminCompetitionRequests'.$myCompetition['id'], $myCompetition['requests']}

tam sice predavas parametre lenze tu:

protected function createComponentRequestsForm($name)
{
	return new AdminCompetitionsRequests();
}

ich nikde nevyuzivas a teda sa v danej classe AdminCompetitionsRequests nikdy nenastavi to $rIds.

Flipajs
Člen | 29
+
0
-

Dobřé, ale jak to mám tedy udělat? Pokud zadám:

protected function createComponentRequestsForm($name, $rIds)
{
        return new AdminCompetitionsRequests($name, $rIds);
}

dostanu Warning: Missing argument 2 for UsermainPresenter::createComponentRequestsForm(), called in…

Pokud někdo může, ukažte prosím jakým způsobem předávat z template ten parametr přes továrnu komponentě.

Díky!

Editoval Flipajs (19. 12. 2010 13:04)

Aurielle
Člen | 1281
+
0
-

Takhle to nejde. Továrnička má jen jeden parametr a to je $name. Parametry, které předáváš při volání makra, se předávají funkci render, takže si je zpracuj tam.

Flipajs
Člen | 29
+
0
-

Reagoval jsem na westerna…

V componentě to dělám tak jak podle mě popisuješ, tedy:

public function render($name, $rIds)
{
        $this->rIds = $rIds;
        $this->getComponent('form')->render();
}

/** @var array */
public $rIds;

Dokonce i když si v createComponentForm dumpnu $this->rIds tak v něm je to co má být.
V formu provádím: $form->addRadioList(‚request_ida‘.$i, $this->rIds[0][‚login‘], $requestRadio);

Po odeslání formu jako by se vůbec $this->rIds nepředalo. Form se odešle se vším všudy, ale kde bylo použito $rIds tak je problém a vážně nevím co s tím :-/

Editoval Flipajs (19. 12. 2010 13:04)

westrem
Člen | 398
+
0
-

Ach .. vidim, ze bude treba obsirnejsie vysvetlit ..
Za prve mas tam cudne carovanie s tym $rIds:

// este OK
public function render($name, $rIds)
        {
                $this->rIds = $rIds;
                $this->getComponent('form')->render();
        }

// ..
// tu je ten parameter druhy zbytocny, pretoze sa nedosadzuje
protected function createComponentForm($name, $rIds)
        {
                    $requestRadio = array('confirmed' => 'confirm', 'waiting' => 'wait', 'declined' => 'decline');

                   $this->rIds = $rIds; // Zbytocne
                    $this->rIds = (array)$this->rIds; // pretypovanie mozes riesit uz v tej metode predtym

                    $form = new AppForm();

                    Debug::dump($this->rIds);

                    $form->addText("test", "Test");

                    $i = $this->rIds[0]['login'];
                    $form->addRadioList('request_ida'.$i, $this->rIds[0]['login'], $requestRadio);
                    $form->addHidden('test2')->setValue($this->rIds);
                    $form->addSubmit('odeslat', 'Odeslat');

                    $form->onSubmit[] = array($this, 'requestListSubmitted');
                    return $form;
        }

Tvoj hlavny problem je ale uplna tradicna zalezitost .. ty tie parametre generujes az v render fazi a predavas ich formularu len potom, to znamena, ze pri vykonani public function requestListSubmitted(AppForm $form) sa ti zakonite nevygeneruje tebou pozadovany formular.

Upravil by som to teda tak, ze by som si potrebne parametry generoval v actionDefault v presenteri, ulozil do premennej presenteru a pri volani createComponentRequestsForm kde vytvaras tu komponentu, ich tam nastavil.

Dufam, ze uz je to jasnejsie ;)

westrem
Člen | 398
+
0
-

O zivotnom cykle presenteru a to ake metody sa kedy volaju sa docitas v prislusnej dokumentacii. Control ma tiez svoju dokumentaciu

Flipajs
Člen | 29
+
0
-

Upravil by som to teda tak, ze by som si potrebne parametry generoval v actionDefault v presenteri, ulozil do premennej presenteru a pri volani createComponentRequestsForm kde vytvaras tu komponentu, ich tam nastavil.

No není mi pořád ještě jasné jak v createComponentRequestsForm poznám které hodnoty mám přiřadit (Těch formů se genreuje více)…

Jsem z toho jelen :-/ :-x

Editoval Flipajs (19. 12. 2010 15:12)

Filip Procházka
Moderator | 4668
+
+1
-

asi jsem to možná nečetl ani celé, ale mohla by pomoct malá nápověda: i v komponentě můžou být persistentní parametry ;)

Flipajs
Člen | 29
+
0
-

Z toho co jsem četl v jiných problémech a bylo mi řečeno tady jde o to, že předávám ty parametry až v renderu což už je pozdě tedy po kliknutí na odeslat jako by neexistovaly a na to nevím jestli by persistentní parametr pomohl. Stejně by se nic nepřeneslo, protože by s tím ten form ještě nepočítal, ne?

Potřebuju vědět jak provést toto:
„Upravil by som to teda tak, ze by som si potrebne parametry generoval v actionDefault v presenteri, ulozil do premennej presenteru a pri volani createComponentRequestsForm kde vytvaras tu komponentu, ich tam nastavil.“

jak zjistit který form se zrovna v tempalte vytváří a získat si někde z té proměnné presenteru ty hodnoty a ty nastavit té komponentě?

Filip Procházka
Moderator | 4668
+
0
-

pokud to zapíšeš pomocí $presenter->parametr = 5 tak by persistence mohla pomoct, zkus :)

Flipajs
Člen | 29
+
0
-

Netuším jak je to myšleno… Jak se z té componenty potom dostanu na ten původní presenter a jak budu vědět čím to mám naplnit?

v templates

{control requestsForm, 'adminCompetitionRequests'.$myCompetition['id'], $myCompetition['requests']}

potřebuju prostě ten parametr co tam posílám dostat ještě před renderováním do té componenty a na základě toho vytvořit formulář. Jak bylo navrženo naládovat to někde v presenteru v ActionDefault do nějaké proměnné… Na tom nerozumím tomu, jak pak v továrničce zjistím který formulář to zrovna je? (protože tam mi nechodí ještě žádný parametr)…

Filip Procházka
Moderator | 4668
+
0
-

v první řadě takový menší detail

{control requestsForm, 'adminCompetitionRequests'.$myCompetition['id'], $myCompetition['requests']}

je docela zbytečné…


říkal jsem si, že by ti mohlo vyhovovat něco takového:

{control requestsForm, $myCompetition}

komponenta:

class RequestsForm extends Nette\Application\Control
{
	/** @persistent */
	public $rId;



	protected function attached($presenter)
	{
		// vytvoříme formulář, aby mohl příjmout signál
		// z principu stačí vytvořit ve výchozím stavu pouze jeden formulář,
		// protože nette dovoluje zpracovat pouze jeden signál v jednom requestu
		$this->createAndAttach($this->rId)
		// o zbytek se postará životní cyklus

		parent::attached($presenter);
	}


	// pro renderování hromady formulářů pro každý competition zvlášť
	public function render($competition)
	{
		$form = $this->createAndAttach($competition['id']);
                $form->render();
	}


	protected getReceiverFormName($id)
	{
		return 'adminCompetitionRequests'. $id;
	}


	protected function createAndAttach($id)
	{
		$name = $this->getReceiverFormName($id);
		$this[$name] = $this->createForm($id);

		// tady je trošku magie, možná to bude chtít poladit, aby to generovalo správný tvar
		$fullname = $this->lookupPath(get_class($this));
		$this[$name]->action->setParam($fullname . self::NAME_SEPARATOR . 'rId', $id);

		return $this[$name];
	}


	protected function createForm($rId)
        {
		$requestRadio = array('confirmed' => 'confirm', 'waiting' => 'wait', 'declined' => 'decline');

		$form = new Nette\Application\AppForm();

		// nevím jak ten formulář má přesně fungovat, ale něco takového by mohlo být asi jak jsi to myslel
		$form->addText("test", "Test");
		$form->addRadioList('request_ida', $rId, $requestRadio);
		$form->addHidden('rId')->setValue($rId);
		$form->addSubmit('odeslat', 'Odeslat');

		$form->onSubmit[] = array($this, 'requestListSubmitted');

		return $form;
        }


	public function requestListSubmitted(Nette\Application\AppForm $form)
	{
		dump($form->getValues());
	}
}

presenter:

protected function createComponentRequestsForm($name)
{
	return $form = new RequestsForm($this, $name);
}

Když o tom tak přemýšlím, tak jestli tohle funguje, tak je to vlastně univerzální řešení pro více stejných formulářů na stránce :)

Editoval HosipLan (19. 12. 2010 18:21)

Flipajs
Člen | 29
+
0
-

EDIT: asi už blbnu, něco na tom řešení bude, projdu to a zdá se, že by to i mohlo fugnovat. Omlouvám se, to je tak když do toho člověk tvrdohlavě civí a pořád to nějako zkouší a nedá si pauzu :-x

Editoval Flipajs (19. 12. 2010 20:44)

Flipajs
Člen | 29
+
0
-

Tak jsem to vyzkoušel.

Hlásí mi to toto:

InvalidStateException

Component ‚requestsForm‘ is not attached to ‚RequestsForm‘.

Napadlo mě (ale asi je to blbost :-x) v presenteru udělat v cyklu něco jako
$requests = new RequestsForm($this, ‚adminCompetitionRequests‘.$myCompetitions[$i][‚id‘]);

Pak se objeví toto:

InvalidStateException

Component ‚adminCompetitionRequests17‘ is not attached to ‚RequestsForm‘.

Ještě nějaký nápad kde by mohla být chyba? Co s tím? Díky!

Flipajs
Člen | 29
+
0
-

Tak nakonec jsem to vyřešil takto:

public function actionDefault()
{
	//nějaké získání $myCompetitions...
	for($i = 0; $i < count($myCompetitions); $i++)
	{

            $request = new AdminCompetitionsRequests;
            $request->setValues((array)$myCompetitions[$i]);

            $this['adminCompetitionRequests'.$myCompetitions[$i]['id']] = $request;
	}
}

V componentě:

public function setValues($rIds)
{
          $this->rIds = (array)$rIds;  //prostě předání nějakých těch parametrů co potřebuju pro vytvoření formu
}

A nakonec templates:

probíhá v foreach...
{control "adminCompetitionRequests".$myCompetition['id']}

Zatím se zdá, že to funguje. Děkuju všem za pomoc. Snad tohle pomůže do budoucna nějaké podobné lamě jako jsem já. (I když nevím jestli je to úplně čistý řešení)…

Editoval Flipajs (20. 12. 2010 22:57)

Filip Procházka
Moderator | 4668
+
0
-

Ach kdy se naučíte používat foreach :)

public function actionDefault()
{
	//nějaké získání $myCompetitions...
	// for($i = 0; $i < count($myCompetitions); $i++)
	foreach ($myCompetitions as $competition)
	{
		$request = new AdminCompetitionsRequests;
		// $request->setValues((array)$$myCompetitions[$i]);
		$request->setValues((array)$competition);

		// $this['adminCompetitionRequests'.$myCompetitions[$i]['id']] = $request;
		$this['adminCompetitionRequests'.$competition['id']] = $request;
        }

	// žádná kouzla s ID, pouze komponenty, které opravdu chci
	$this->template->competitions = $this->getComponents(FALSE, 'AdminCompetitionsRequests');
}
{foreach $competitions as $component}
	{control $component}
{/foreach}

To moje je sice o několik řádů víc magické, ale příjde mi to mnohem víc efektivnější :)

Editoval HosipLan (21. 12. 2010 0:34)