Nette Framework
  • Úvodní stránka
  • Download
  • Dokumentace
  • Fórum
  • Blog
  • Přispějte
  • Quick Start
    • Začínáme
    • Adresářová struktura
    • Vytvoření presenteru
    • Připojení šablony
    • Tvorba odkazů
    • Hezčí šablony
    • Zobrazení tabulky
    • Stránkování a řazení
    • Tvoříme komponentu
  • Nette\Annotations
  • Nette\Application
    • Application
    • AppForm
    • Control
    • Presenter
    • PresenterCompo­nent
    • PresenterRequest
    • Routování
    • MultiRouter
    • Route
    • SimpleRouter
  • Nette\Caching
  • Nette\Component
  • Nette\Debug
    • Základy
    • Logování chyb
    • Firebug
  • Nette\Environment
  • Nette\Forms
  • Nette\IO\SafeS­tream
  • Nette\Loaders
  • Nette\Object
  • Nette\Security
    • Bezpečnost aplikací
    • Identity
    • SimpleAuthenti­cator
    • Permission
    • Dynamická správa rolí a zdrojů
  • Nette\String
  • Nette\Templates
    • Template
    • Template Filters
    • Template Helpers
  • Nette\Web\Html
  • Nette\Web\HttpR­equest
  • Nette\Web\HttpR­esponse
  • Nette\Web\Session
  • Nette\Web\User
Naposledy změněno 19. 11. 2008 Edituj Historie Poslední změny

Nette\Applica­tion\AppForm

Třída AppForm je navržena speciálně pro použití v presenteru – má obslužné mechanismy na zpracování signálů. Od třídy Form se liší také tím tím, že má převrácené argumenty v konstruktoru (Form má jako první argument jméno a až jako druhý rodičovský IComponentCon­tainer). Třída Form má parametr $parent uvedený až „bokem“ proto, že tam, kde se používá, obvykle žádný parent není potřeba a ani neexistuje.

AppForm využívá ke svému zpracování handlery. Ty se zpracovávají v metodě prepare{View} a fázi state changing v životním cyklu presenteru, proto je musíme zaregistrovat právě zde.

Metoda onSubmit se volá jen v případě, že je formulář skutečně odeslán, není potřeba znovu kontrolovat přes isSubmitted. Maximálně pokud můžeme zjistit, jakým prvkem byl formulář odeslán. onSubmit se provede pouze pokud byl formulář úspěšně a validně odeslán.

Obslužné handlery musíme nějak výstižně pojmenovávat, nesmí se nám zaměňovat název s metodou handle{Signal}. Takovou klasikou bývá {componentName}_{event}, tedy třeba loginForm_onSubmit. To ale záleží na uvážení programátora. Tato metoda také pobírá jeden argument, kterým je instance formuláře.

Obsluha událostí

Pro obsluhu událostí se doporučuje používat následující vzor (viz Best practice: Formulářová tlačítka):

class SomePresenter extends BasePresenter
{
    /** @var Form */
    public $form;

    ...

    public function prepareDefault()
    {
        // definice formuláře
        $form = new AppForm($this, 'formName');
        $form->addText('name', 'Your name:');
        $form->addSubmit('ok', 'Send')
                ->onClick[] = array($this, 'OkClicked'); // nebo 'OkClickHandler'
        $form->addSubmit('cancel', 'Cancel')
                ->setValidationScope(FALSE) // prvek se nebude validovat
                ->onClick[] = array($this, 'CancelClicked'); // nebo 'CancelClickHandler'

        // alternativa:
        $form->onSubmit[] = array($this, 'FormSubmitted'); // nebo 'FormSubmitHandler'


        if (!$form->isSubmitted()) {
                // první zobrazení, nastavíme výchozí hodnoty
                $form->setDefaults($defaults);
        }

        $this->form = $form;
    }


    // obslužné handlery:
    public function OkClicked(SubmitButton $button)
    {
        // submitted and valid
        Debug::dump($form->getValues());
        redirect(...);
    }

    public function CancelClicked(SubmitButton $button)
    {
        // process cancelled
        redirect(...);
    }

    public function FormSubmitted(Form $form)
    {
        // manual processing
        if ($form['cancel']->isSubmittedBy()) { ... }
    }
}

Obslužný handler pro onSubmit lze použít v případě, kdy formulář nemá žádné nebo právě jedno tlačítko. V odstatních situacích bývá vhodnější využít handler onClick přímo na tlačítku.

Handler onClick se volá před handlerem onSubmit. Handlery se volají pouze v případě, že je odeslání validní. Uvnitř metody OkClicked tedy není nutné ověřovat validitu formuláře. Naopak metoda FormSubmitted může být zavolána i v případě nevalidního formuláře, byl-li odeslán tlačítkem Cancel.

V případě, že formulář nebyl odeslán tlačítkem (například byl odeslán přes JavaScript), nebo se tak tváří kvůli chybě v Internet Exploreru, bude Nette za odesílací tlačítko považovat první tlačítko formuláře. Tudíž obsluha přes události onClick je spolehlivá.

Obslušné handlery se vyvolají při prvním volání metody isSubmitted() nebo processHttpRequest(), při použití uvnitř Nette\Application vyvolání zajistí samotný presenter.

Kontrola odeslání formuláře

Použití kontroly odeslání formuláře by mohlo vypadat takto:

if ($form->isSubmitted()) { ... }

Přídklad by nám vrátil objekt implementující rozhraní ISubmitterControl (nejčastěji objekt SubmitButton) v případě, že je formulář odeslán nebo FALSE jestliže není. Nevadí, že vrácená hodnota je objekt, podmínka se vyhodnotí korektně.

Můžeme se dotázat, přímo byl formulář odeslán přes konkrétní tlačítko:

if ($form['preview']->isSubmittedBy()) { ... }

Tímto způsobem je i možné postihnout případné složitější struktury:

if ($form['subform']['preview']->isSubmittedBy()) { ... }

Validace jednotlivých prvků formuláře

U každého tlačítka je možné nastavit, jestli vyžaduje validaci:

$form->addSubmit('cancel', 'Cancel')
    ->setValidationScope(FALSE); // nebude se nic validovat

Funkce se jmenuje tak proto, že se plánuje její rozšíření o možnost předat pole nebo skupinu (to zůstává k diskusi) prvků, na které se validace při stisku tlačítka omezí.

Vynechání prvku z vykreslování

$form['save']->setRendered(TRUE);

Tímto zavoláním vynecháme prvek z vykreslování. Formulář ho pak považuje za vykreslený, tudíž ho nevykreslí, a my si jej pak můžeme vykreslit v šabloně ručně. To se hodí v případech, kdy chceme například vykreslit samostatně více odesílacích tlačítek vedle sebe.

Příklad více formulářů na jedné stránce

class SomePresenter extends BasePresenter
{
    /** @var Form */
    public $form1;

    /** @var Form */
    public $form2;

    ...

    public function prepareDefault()
    {
        $form1 = new AppForm($this, 'form1');
        // ... definice formuláře 1
        $form1->onSubmit[] = array($this, 'form1_onSubmit');

        $form2 = new AppForm($this, 'form2');
        // ... definice formuláře 2
        $form2->onSubmit[] = array($this, 'form2_onSubmit');

        $this->form1 = $form1;
        $this->form2 = $form2;
    }

    ...

    public function form1_onSubmit(AppForm $sender)
    {
        // Zpracování form1
        Debug::dump($sender->getValues());
    }

    public function form2_onSubmit(AppForm $sender)
    {
        // Zpracování form2
        Debug::dump($sender->getValues());
    }
}

Defaultně action formuláře ukazuje na stejný view/scene se stejnými parametry, jen se do URL přidá signál (?do=form1-submit), který Nette předá příslušnému formuláři a ten se podle toho zařídí (zavolá si metody definované v onSubmit). Pokud se má formulář odesílat do jiného view, tak je potřeba ten signál přidat do argumentů.

Iterování nad formulářem

K iterování nad formulářem stejně jako nad polem svádí zápisy $form['name']->... tedy:

foreach ($form as $name => $component) { ... }

což je samozřejmě možné, ale zvažme, že ne každá komponenta $form je prvek FormControl. Můžou tam být jakékoliv jiné komponenty, nebo kontainery, které teprve obsahují prvky formuláře, případně další kontainery atd. Pro iterování je lepší použít šikovnou metodu $form->getComponents($deep = FALSE, $type = NULL), kde první parametr říká, zda se má iterovat do hloubky (tj. projít i prvky konteinerů) a druhý nastavuje volitelný filtr:

foreach ($form->getComponents(TRUE, 'Nette\Forms\IFormControl') as $control) {
    $control->setValue(...);
}

Viz také:

  • Best practice: Formulářová tlačítka
  • Vlastní vykreslování formulářů
  • Formuláře, podmínky a pravidla
  • Zprávy z modelu do formuláře
« Application Control »

Nette Framework powered | dibi powered | Texy! powered | Institut Školení PHP