Undefined variable: _form při invalidaci jedné kontrolky formuláře

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

Něco podobného se už pravděpodobně řešilo, ale samotné řešení se mi nikde najít nepodařilo. Jde o to, že mám formulář, ve kterém jsou dva select boxy, kde jeden má obsahovat seznam krajů a druhý seznam okresů v daném kraji. Vycházel jsem z tohoto návodu, který se přesně zabývá mým problémem.

presenter:

public function handleSelectLoad($kraj) {
        $form = $this->getComponent("registracniFormularPoptavajici");
        $form["kraj"]->setDefaultValue($kraj);
        $form["okres"]->setItems($this->context->createOkresy()->where(array("id_kraje" => $kraj))
                ->fetchPairs("id_okresu", "nazev_okresu"));
        $this->invalidateControl("form");
    }

šablona1:

<fieldset>
    <legend>Registrační formulář</legend>
    {form registracniFormularPoptavajici}
        {label email /} {input email}<br/>
        {label heslo /} {input heslo}<br/>
        {label hesloCheck /} {input hesloCheck}<br/>
        {label jmeno /} {input jmeno}<br/>
        {label kraj /} {input kraj}<br/>
        {snippet form}
        {label okres /} {input okres}<br/>
        <script>
            $("form").delegate('#'+{$control["registracniFormularPoptavajici-kraj"]->htmlId}, 'change', 	                     function() {
                $.get("?do=selectLoad", {"kraj": $(this).val()});
            });
        </script>
        {/snippet}
        {input registerPop}<br/>
    {/form}
</fieldset>

šablona2:

{snippet form}
<fieldset>
    <legend>Registrační formulář</legend>
    {form registracniFormularPoptavajici}
        {label email /} {input email}<br/>
        {label heslo /} {input heslo}<br/>
        {label hesloCheck /} {input hesloCheck}<br/>
        {label jmeno /} {input jmeno}<br/>
        {label kraj /} {input kraj}<br/>
        {label okres /} {input okres}<br/>
        <script type="text/javascript">
            $("form").delegate('#'+{$control["registracniFormularPoptavajici-kraj"]->htmlId}, 'change', function() {
                $.get("?do=selectLoad", {"kraj": $(this).val()});
            });
        </script>
        {input registerPop}<br/>
    {/form}
</fieldset>
{/snippet}

Šablona 1 má ve snippetu zabalený pouze select box, který se má měnit. Přesně tak, jak je to řečeno v návodu. Když to ale spustím, tak mi laděnka vyhodí chybu: Undefined variable: _form. Co jsem tak pochopil, tak je to proto, že se obsah snippetu vyjme z původního kódu a tam už pak proměnná _form není k dispozici. Tím si ale nejsem vůbec jistý. Takto to každopádně nefunguje vůbec a to ani když vemu příklad přímo z pla.nette. Háže to stejnou výše jmenovanou chybu. Mou otázkou na toto řešení je, jestli někde dělám chybu nebo jestli jsem někde něco přehlédl? Nebo jestli někdo neví, v čem by mohl být problém?

Šablona 2 má ve snippetu zabalený celý formulář. V tuhle chvíli se celá stránka načte a při změně kraje se dokonce i správně naplní obsah druhé select boxu s příslušnými okresy. Problémem ale je, že se invaliduje úplně celý formulář a všechny ostatní vyplněné hodnoty se při změně kraje smažou. V tomto řešení by mě zase zajímalo, jak uchovat všechny už vyplněné hodnoty ve formuláři? Přikláním se ale spíše k řešení z první šablony, protože mi přijde logicky lepší obnovovat pouze jednu kontrolku.

V dokumentu z pla.nette, z kterého vycházím, je rozdíl pouze v tom, že já zahrnuji script přímo do snippetu a ne mimo něj. To z toho důvodu, že když je mimo, tak se změna provede jen jednou a při každé další změně kraje už ne.

To bude nejspíš vše. Je to můj první příspěvek a předem se kdyžtak omlouvám za špatné formátování a i za to, jestli jsem náhodou řešení mého problému jen nepřehlédl. Předem mockrát díky za jakoukoli pomoc nebo alespoň naťuknutí!

Tomáš Votruba
Moderator | 1114
+
0
-

Zkus do funkce přidat

$this->template->_form = $form;

Viz tady

PatrioScraper
Člen | 3
+
0
-
public function handleSelectLoad($kraj) {
        $form = $this->getComponent("registracniFormularPoptavajici");
        $form["kraj"]->setDefaultValue($kraj);
        $form["okres"]->setItems($this->context->createOkresy()->where(array("id_kraje" => $kraj))
                        ->fetchPairs("id_okresu", "nazev_okresu"));
        $this->template->_form = $form;
        $this->invalidateControl("form");
}

Doplnil jsem řádek, jak jsi mi poradil, ale žádná změna. Už jsem to myslím dneska jednou zkoušel, ale bez úspěchu. V laděnce svítí tenhle řádek:

<?php if ($_label = $_form["okres"]->getLabel()) echo $_label->addAttributes(array()) ?>
Tomáš Votruba
Moderator | 1114
+
0
-

$_form musí existovat i při renderu formuláře, ne jen při jeho invalidaci. Zkus tedy:

public function renderDefault()
{
	$this->template->form = $this->template->_form = $this["form"];
}

(Případě do funkce actionDefault, ale tohle by mělo stačit.)

PatrioScraper
Člen | 3
+
0
-

Je to tak. Neuvědomil jsem si to. Pořád se to učím! Mockrát díky, funguje :-)

Tomáš Votruba
Moderator | 1114
+
0
-

Teď mám problém, jak podobnou věc udělat pro 2 formuláře. Tohle mi přijde trochu krkolomné. Navíc mi druhý input vypisuje při invalidaci dvakrát.

{snippet snippetOne}
	{var $_form = $control["formOne"]}
	{input inputOne}
{/snippet}

{snippet snippetTwo}
	{var $_form = $control["formTwo"]}
	{input inputTwo}
{/snippet}