Formulář v presenteru s vykreslením v šabloně

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

Zdravím, po mnoha pokusech a projití snad všeho co na fóru k formulářům je, píšu a prosím o pomoc.

Snažím se vytvrořit například formulář k mailu. Nevím přesně zda je to ok, ale nejvíc se mi líbí varianta definice formuláře v presenteru pro mail a jeho vykreslení v šabloně pro mail.

V presenteru mám zatím toto:

protected function createComponentMailForm($name)
    {
        // definice formuláře
        $form = new AppForm($this, $name);
        $form->addText('subject');
        $form->addTextArea('note');
        $form->addText('name');
        $form->addText('email')->setEmptyValue('@');
        $form->addSubmit('cancel', 'Smazat');
        $form->addSubmit('ok', 'Odeslat');

        // definice validačních pravidel
        $form['subject']->addRule(Form::FILLED, 'Uveďte předmět zpravy.');
        $form['note']->addRule(Form::FILLED, 'Napište text Vaší zprávy.');
        $form['name']->addRule(Form::FILLED, 'Uveďte Vaše jméno.');
        $form['email']->addRule(Form::FILLED, 'Uveďte Váši e-mailovou adresu.')
                      ->addRule(Form::EMAIL, 'Zadaná adresa není správnou adresou elektronické pošty.');

        return $form;
    }

Což se mi dáří vykreslit v šabloně pomocí {widget mailForm}.

Zádrhel však nastává u vykreslení v šabloně, kde se pokouším o toto:

<?php $form->render('begin') ?>

  {if !empty($form->errors)}
  <div class="errors">{foreach $form->errors as $error}{$error}<br>{/foreach}</div>
  {/if}

  <div class="...">
    <div class="..."><?php $form['subject']->getLabel('Předmět zprávy:') ?><?php $form['subject']->control->cols(30) ?></div>
    <div class="..."><?php $form['note']->getLabel('Zpráva:') ?><?php $form['note']->control->cols(35)->rows(5) ?></div>
    <div class="..."><?php $form['name']->getLabel('Vaše jméno:') ?><?php $form['name']->control->cols(30) ?></div>
    <div class="..."><?php $form['email']->getLabel('E-mail:') ?><?php $form['email']->control->cols(30) ?></div>
  </div>

<?php $form->render('end') ?>

Zkoušel jsem vykreslení jak pomocí

<?php $form['subject']->getLabel('Předmět zprávy:') ?><?php $form['subject']->control->cols(30) ?>

tak i

<?php echo $presenter['mailForm']['subject']->getLabel('Předmět zprávy:') ?><?php echo $presenter['mailForm']['subject']->control->cols(35) ?>

Při mých pokusech mi však vždy laděnka vyhodila chybu. Zkouším nad verzí 1.0dev.

Cílem toho všeho snažení je dosáhnout po vygenerování něčeho co nejblíže k tomuto (X)HTML kódu, ikdyž to bude bez accesskeys apod.:

<div class="...">
<div class="..."><label for="p"><span class="flunder">P</span>ředmět:</label><input type="text" id="p" accesskey="p" name="predmet" size="30" /></div>
<div class="..."><label for="z"><span class="flunder">Z</span>práva:</label><textarea id="z" accesskey="z" name="zprava" rows="8" cols="30"></textarea></div>
<div class="..."><label for="j">Vaše <span class="flunder">j</span>méno:</label><input type="text" id="j" accesskey="j" name="jmeno" size="30" /></div>
<div class="..."><label for="e">Váš <span class="flunder">e</span>-mail:</label><input type="text" id="e" accesskey="e" name="email" size="30" value="@" /></div>
<div><input class="..." type="reset" value="Smazat" /> <input class="..." type="submit" value="Odeslat" /></div>
</div>

Předem moc díky všem za rady.

LuKo
Člen | 116
+
0
-

Máš v presenteru $this->template->form = createComponentMailForm(); nebo $this->template->form = $this['mailForm'];?

Ola
Člen | 385
+
0
-

Co to píše za chybu? Minimálně následující mi na lokálu funguje:

{? $presenter['mailForm']->render('begin') }

  {if !empty($presenter['mailForm']->errors)}
  <div class="errors">{foreach $presenter['mailForm']->errors as $error}{$error}<br>{/foreach}</div>
  {/if}

  <div class="...">
    <div class="...">{$presenter['mailForm']['subject']->getLabel('Předmět zprávy:')}{$presenter['mailForm']['subject']->control->cols(30)}</div>
    <div class="...">{$presenter['mailForm']['note']->getLabel('Zpráva:')}{$presenter['mailForm']['note']->control->cols(35)->rows(5)}</div>
    <div class="...">{$presenter['mailForm']['name']->getLabel('Vaše jméno:')}{$presenter['mailForm']['name']->control->cols(30)}</div>
    <div class="...">{$presenter['mailForm']['email']->getLabel('E-mail:')}{$presenter['mailForm']['email']->control->cols(30)}</div>
  </div>

{? $presenter['mailForm']->render('end') }
premek
Člen | 15
+
0
-

to Luko: nejprve jsem v presenteru měl $this->template->form = $form;
a později toto $this->template->form = $this->getComponent(‚mailForm‘); s tím i bez toho mi vykreslení přes widget šlo, a jde to i nyní u rady od Ola.

to Ola: Paráda, díky moc, funguje. :) Jinak mi to házelo chyby, u $form->render(‚begin‘);, že je to chybná syntaxe, když jsem dal echo $presenter[‚mailForm‘]->render(‚begin‘); tak to skočilo na další, ikdyž jsme dal vše echo $presenter…, tak to furt hlásilo nějakou neošetřenou chybu / vyjímku. Bohužel přesné hlášky už nevím, zkoušel jsem toliká variant, že už ani nevím jak to vyvolat, raději ;).

premek
Člen | 15
+
0
-

Zdravím, prosím ještě o pár rad a odpovědí, bude-li někdo vedět.

  1. trápí mě problém s class u prvků formuláře – automaticky se vykresluje u labelu class=„required“ a u inputu class=„text“. Dá se nějak udělat to aby se tyto class nevykreslily.
  2. když chci změnit class např. u „tlačítek“ (addSubmit) z button na button1, tak pomocí ->getControlPrototype()->class(‚…‘); se ve vygenerovaném kódu se objeví class=„button1 button“. Prohlížeč si samozřejmě vezme ten první a další ignoruje, ale i tak by mě zajímalo jestli to lze nečím přepsat natvrdo aby bylo jen class=„button1“. Netuším ani jeslti jde o chybu či je to tak standartně, ale mě osobně to přijde divné, jelikož netuším k čemu by mi ten tvar byl dobrej.
  3. při manuálním vykreslování formu (např. u textboxu) „nefunguje“ ->cols(30) či ->rows(5), když ale při definování formu v presenteru dám (‚note‘, ‚Zpráva:‘, 30, 5) jako zde, tak to vezme, když to bude podle tohoto tak ne. Vím, že nemusím uvádět nic (idkyž u textboxu je nastavená defaultní hodnota 40 a 10) jelikož to jde ošetřit pomocí css, ale i tak mě to lehce deptá, jelikož to kazí dojem z toho, že si manuální vykresení celé ošefuju v šabloně (sem tam se stane, že má někdo css vyplé).
  4. neměl by někdo typ nak vykreslit chybu při validaci formuláře ne „vše nad“ či „vedle“, ale „nad“ u každého prvků zvlášť, jako třeba tu.
  5. „opravdu“ se nedá js validace na straně klienta hodit do externího *.js?

Předem díky. :)

premek
Člen | 15
+
0
-

premek napsal(a):

Zdravím, prosím ještě o pár rad a odpovědí, bude-li někdo vedět.

  1. trápí mě problém s class u prvků formuláře – automaticky se vykresluje u labelu class=„required“ a u inputu class=„text“. Dá se nějak udělat to aby se tyto class nevykreslily.
  2. když chci změnit class např. u „tlačítek“ (addSubmit) z button na button1, tak pomocí ->getControlPrototype()->class(‚…‘); se ve vygenerovaném kódu se objeví class=„button1 button“. Prohlížeč si samozřejmě vezme ten první a další ignoruje, ale i tak by mě zajímalo jestli to lze nečím přepsat natvrdo aby bylo jen class=„button1“. Netuším ani jeslti jde o chybu či je to tak standartně, ale mě osobně to přijde divné, jelikož netuším k čemu by mi ten tvar byl dobrej.
  3. při manuálním vykreslování formu (např. u textboxu) „nefunguje“ ->cols(30) či ->rows(5), když ale při definování formu v presenteru dám (‚note‘, ‚Zpráva:‘, 30, 5) jako zde, tak to vezme, když to bude podle tohoto tak ne. Vím, že nemusím uvádět nic (idkyž u textboxu je nastavená defaultní hodnota 40 a 10) jelikož to jde ošetřit pomocí css, ale i tak mě to lehce deptá, jelikož to kazí dojem z toho, že si manuální vykresení celé ošefuju v šabloně (sem tam se stane, že má někdo css vyplé).
  4. neměl by někdo typ nak vykreslit chybu při validaci formuláře ne „vše nad“ či „vedle“, ale „nad“ u každého prvků zvlášť, jako třeba tu.
  5. „opravdu“ se nedá js validace na straně klienta hodit do externího *.js?

Předem díky. :)

Opravdu by se někdo nenašel s radou jak na to. Bod 1 a 2, jsem již vyřešil pomocí ->class(NULL) a ->class(‚button1‘)

Ondřej Mirtes
Člen | 1536
+
0
-

Ke 4): Každý formulářový prvek má metodu getErrors(), můžeš si je tedy v šabloně vytáhnout u každého zvlášť.

Patrik Votoček
Člen | 2221
+
0
-
  1. pomocí wrapperů to můžeš změnit
$form = new AppForm($this, $name);
$renderer = $form->getRenderer();
$renderer->wrappers['pair']['.required'] = NULL;
$renderer->wrappers['pair']['.text'] = NULL;
  1. totéž jako 1čka
  2. co ti brání nastavit to rovnou? ale nastavit by to jít mělo…
  3. viz Ondra
  4. tenhle požadavek slyším prvně. A musím říct že asi by to nějákou úpravou Nette\Forms\ConventionalRenderer šlo. Ale bylo by to dost wtf…
Ondřej Mirtes
Člen | 1536
+
0
-

S tou JS validací je problém ten, že se IMHO generuje dynamicky a nejde tak zobecnit pouze na přiřazování validačních pravidel např. pomocí atributu class. Je to tak hlavně kvůli addConditionOn, jednoduchá pravidla, kde nejsou závislosti mezi formulářovými prvky, by tak udělat šla.

premek
Člen | 15
+
0
-

Díky moc za nakopnutí. :) Ale jsem větší lama než jsem myslel… :(

Ondra: bodl by nějaký jak předat výpis chyby za jeden prvek ve formuláři jsem nevykoumal, vždy mi to buď vyhodí nic (tedy chyby se nezobrazí), nebo všechno vypíše vše jen posunuté mezi prvky formu

vrtak-cz: u té 3) vím, že by to asi mělo jít, jen u mě to nejde a zaboha nevím proč, tak jsem to chtěl nejdříve zkonzultovat abych tady netrapčil s hlášením chyby, která je jak je obvykle zvykem někde mezi zidlí a stolem… Nevím co dělám blbě, ale když si dám vlastní vypsání formuláře takto – že v presenteru určím velikost textarea tak to šlape:

v presenteru:
...
$form->addTextArea('zprava', '', 55, 5);
...

v šabloně:
...
<div class="mftextpad">{$presenter['mailForm']['zprava']->getLabel('Zpráva:')->class(NULL)}{$presenter['mailForm']['zprava']->control->class(NULL)}</div>
...

výsledný html:

...
<div class="..."><label for="frmmailForm-zprava">Zpráva:</label><textarea cols="55" rows="5" name="zprava" id="frmmailForm-zprava"></textarea></div>
...

když to, ale udělám takto:

v presenteru:
...
$form->addTextArea('zprava');
...

v šabloně:
...
<div class="mftextpad">{$presenter['mailForm']['zprava']->getLabel('Zpráva:')->class(NULL)}{$presenter['mailForm']['zprava']->control->cols(55)->rows(5)->class(NULL)}</div>
...

výsledný html:

...
<div class="..."><label for="frmmailForm-zprava">Zpráva:</label><textarea cols="55" rows="5" name="zprava" id="frmmailForm-zprava"></textarea></div>
...

tak se u textarea nastaví default či co z nette a moje nastavení jde dokopru, respektive obrazový efekt žádný…