Egoblog.cz - Petr Kobelka

Nette a Multiple Form

Jistě jste se v Nette setkali např. s tvorbou e-shopu, kdy potřebujete mít na stránce vícekrát stejný formulář. Tenhle článek Vám ukáže jak na to.


PHP | Komentáře (0) | Shlédnuto 6480 × | Vloženo: 3. září 2014

V jednoduchosti Vám tento post představí řešení jak v jedné stránce použít jeden formulář více násobně. Můj problém nebyl v e-shopu, ale v trochu jiné aplikaci. Jeho základ byl ale stejný. Potřeboval jsem v jedné stránce mít více stejných formulářů, které se lišily jen nějakým ID a každý má různá data.

Jedno z možných řešení je naplnit data při vykreslování, tedy pokud jako já vykreslujete formuláře ručně. Používám při tvorbě aplikací v Nette Boostrtrap a to je důvod, proč vykresluji formuláře ručně. Určitě lze napsat vlastní render, ten ale nedokáže dobře podchytit specifické formuláře, nebo by jeho napsání bylo zbytečně složité a trvalo neúměrně dlouhou dobu.

Zdroje o Nette a Forms

Základem pro moje řešení jsou tyto tři články, díky jejich kombinaci spolu s dosaženými vědomostmi při práci v Nette vedly k úspěšnému cíli.

První krok, ujasnit si cíle

Chtěl jsem mít formulář použitelný ve více různých stránkách, proto pro mě byla jasná volba použít jej jako komponentu (Control). V jiném případě můžete celý proces zjednodušit a tvorbu formuláře umístit přímo do požadovaného presenteru.

Založení nové komponenty (Control)

V adresáři, kam ukládám komponenty, obvykle /app/controls jsem založil nový adresář MultipleForm. Názvy jsou pouze ilustrační, protože kdybych použil originální, nejspíš by Vám to moc nepomohlo.

Dále jsem v adresáři MultipleForm vytvořil 3 nové soubory:

  • MultipleForm.php
  • MultipleForm.latte
  • MultipleFormFactory.php

"Uvedené příkladu souborů jsou ilustrační a nebyly přímo testovány. Vychází ale z odzkoušeného problému a těla metod jsou vyčištěna od nepotřebných dat."

Soubor MultipleForm.php

Soubor obsahuje řídící informace pro práci s formulářem, tedy jeho definici, obsluhu události odeslání formuláře v Nette. Ukázku souboru máte níže.

/**
 * formular pro vicenasobne pouziti
 */
use Nette,
    Nette\Application\UI\Control,
    Nette\Application\UI\Form;
use Nette\Application\UI\Multiplier;

class MultipleForm extends Control
{
 /**
   *
   * @var int
   */
  private $id = 0;
  /**
   *
   */
  public function __construct()
	{
	}
  /**
   * @access public
   */
  public function render($params)
  {
    $this->id = $params['id'];

    $template = $this->template;
    $template->setTranslator($this->trans);
    $template->setFile(__DIR__.'/MultipleForm.latte');
    $template->id = $this->id;

    $template->render();
  }
  /**
   *
   */
  public function createComponentForm()
  {
    return new Multiplier(function ()
    {
      $form = new Form();

      $form->addHidden('id', $this->id);
      $form->addText('date', 'Datum');
      

      $form->addSubmit('submit', 'Ulož');

      $form->onSubmit[] = $this->save;

      return $form;
    });
  }
  /**
   *
   * @param \Nette\Application\UI\Form $form
   */
  public function save(Form $form)
  {
    $vals = $form->getHttpData();
    $data = [];
    
    // zde zpracuji odeslana data formularem

    $this->flashMessage('Záznam byl uložen', 'success');
    $this->redirect('this');
  }
}

Ve výše uvedeném souboru je SUPER DŮLEŽITÉ použití nástroje Multiplier, které je tou alfou-omegou celého řešení. Nedohledal jsem, od kdy je tento nástroj v Nette, ale první zmínku jsem našel z roku 2012. Více informací najdete např na adrese http://pla.nette.org/cs/multiplier.

Soubor MultipleForm.latte

Šablona formuláře. Z určitých důvodů často formuláře vykresluji ručně. Jeho vzhled a formátování je uloženo v tomto souboru.

{form form-$id}
  {input id}
  <div class="row">
    <div class="col-sm-2 col-sm-offset-4">
      {label date /}
      {input date, class => 'form-control input-sm datePicker'}
    </div>
    <div class="col-sm-2">
      <br />
      {input submit, class => 'btn btn-primary'}
    </div>
  </div>
{/form}

MultipleFormFactory.php

Továrnička pro vytvoření instance formuláře ve stránce. Továrničku dle potřeby injektujete do presenteru, kde chcete formulář použít.

/**
 * interface pro formular
 */
interface IMultipleFormFactory
{
  /**
   * @return \MultipleForm
   */
  function create();
}

Injektování formuláře do presenteru

Nejdříve je třeba továrničku deklarovat do config.neon jako services. Konfigurační soubor rozšiřte o řádek, který bude vypadat asi takto:

  - \IOrderPaidFormFactory

Dále je třeba injektovat třídu do presenteru v němž chcete formulář využívat. Příklad takového presenteru:

use Nette;
use Nette\Application\UI\Form;
use Nette\Mail\Message;
use Nette\Mail\SendmailMailer;
/**
 *
 */
class ExamplePresenter extends BasePresenter
{
  /**
   * @persistent
   */
  public $id;
  /**
   *
   * @var \IMultipleFormFactory
   */
  private $multipleForm;
  /**
   *
   * @param \IMultipleFormFactory $factory
   */
  public function injectIMultipleFormFactory(\IMultipleFormFactory $factory)
  {
    $this->multipleForm = $factory;
  }
  /**
   *
   */
  public function createComponentMultipleForm()
  {
    return $this->multipleForm->create();
  }
}

V uvedeném příkladu presenteru injektujete nástroj pro vytvoření formuláře do presenteru, kde jej budete chtít použít.

V čem spočívá ta magie?

To je dobrá otázka. Ta hlavní magie je v šabloně:

{form form-$id}

Tedy hned v tom prvním řádku. Uvedená deklarace je závazná, použiteje název formuláře a klíč. Obě hodnoty oddělíte pomlčkou.

Druhá část magie je v použití nástroje Multiplier který způsobí, že Vám laděnka nevrátí chybu o neexistujícím formuláři. Proces, který nastane je ten, že se Nette pokusí inicializovat formulář "Form" a předá mu v parametru hodnotu klíče ($id) -> název byl form-$id.

Díky tomuto můžete využít stejný formuláře vícekrát v jedné stránce a inicializovat jej různými daty. Kdyby jste nepoužili Multiplier, byly by všechny formuláře stejné a měly stejná data!

Vložení komponenty vícenásobného formuláře do stránky

Už se dostáváme k další důležité části. Jak komponentu s formulářem vložit do stránky. Moje odpověď je - jednoduše :-)

{control orderPaidForm, id => $id}

Pomocí controlu můžete předat parametry, které následně využijete při generování formuláře.

Petr Kobelka | Egoblog.cz | Tvorba www stránek - www.petrkobelka.cz

Petr Kobelka
Autor je zkušeným web developerem a programátorem s více než 10 letými zkušenostmi. Pracuje jako programátor pro známou Olomouckou společnost zabývající se tvorbou internetových a intranetových řešení. Spolu se zaměstnáním pracuje na volné noze a zabývá se tvorbou internetových stránek. Ve volném čase rád fotí, jezdí na kole, plave a cestuje.

Komentáře

E-mail je potřeba pouze pro vygenerování Gravataru!

Oups, žádné komentáře? Buďtě první !!!

Blog píše Petr Kobelka

Petr Kobelka - egoblog.cz

Žádám všechny, kteří mají zájem vkládat komentáře, aby se řídili pravidly NETikety. Komentáře, porušující tato pravidla můžou být bez varování smazány.