Skip to content

Instantly share code, notes, and snippets.

@zraly
Last active February 11, 2020 19:19
Show Gist options
  • Save zraly/be3fee179897ed1851a9 to your computer and use it in GitHub Desktop.
Save zraly/be3fee179897ed1851a9 to your computer and use it in GitHub Desktop.
Formulář jako komponenta s vlastní šablonou / Form as a component with its own template
# EN: we have to add the form interface into services
# CS: interface formuláře si přidáme do služeb
services:
- \IFooFormFactory
{form myForm}
<div class="form-group">
{label book class => 'control-label'/}
{input book class => form-control}
</div>
<div class="form-group">
{input send class => 'btn btn-primary'}
</div>
{/form}
<?php
use Nette,
Nette\Application\UI;
class FooForm extends UI\Control
{
// EN: define Nette event http://doc.nette.org/en/2.2/php-language-enhancements#toc-events
// CS: definujeme si Nette Event http://doc.nette.org/cs/2.2/php-language-enhancements#toc-udalosti
public $onFormSuccess;
// EN: define our variables, which we will need to process the form
// CS: definujeme si vlastní proměnné, které potřebujeme při zpracování formuláře, například pro uložení dat
private $books;
private $fooParam;
// EN: if we need to send some parameters to our form, let's do it through constructor
// CS: pokud si do formuláře potřebujeme předat nějaké parametry, uděláme to skrz konstruktor
public function __construct($fooParam, BookRepository $books)
{
$this->books = $books;
$this->fooParam = $fooParam;
}
/**
* @return Form
*/
protected function createComponentMyForm()
{
$form = new UI\Form;
$form->addText('book', 'Název knihy:');
$form->addSubmit('send', 'Vložit knihu');
$form->onSuccess[] = $this->processForm;
return $form;
}
public function processForm($form, $values) {
// EN: here form values are processed, we can use our variables from constructor
// CS: zde můžeme si zpracujeme data odeslané formulářem
// a můžeme využít proměnné z konstruktoru
// EN: now we need to call the event we defined. It is because we will add more process stuff
// which will be specific for a presenter. E.g. $this–>redirect('some:where')
// CS: zde je potřeba zavolat vlastní událost, abychom mohli v presenteru na ni navěsit
// další zpracování formuláře, které bude typické pro to konkrétní využití formuláře
// v presenteru. Například $this->redirect('Pokazde:jinam') apod.
$this->onFormSuccess();
}
// EN: assign own template to the form
// CS: formuláři přiřadíme jeho vlastní šablonku, která je uložena v souboru hned vedle
public function render()
{
// EN: we have to send this variable into template at least to render the form with macros
// CS: do šablony je potřeba přidat alespoň tuto proměnnou, abychom formulář mohli vykreslit pomocí maker
$this->template->render(__DIR__ . '/FooForm.latte');
}
}
// EN: create an interface, which will help us inject the form into a presenter
// it has to have only one method create(), which contains parameters that is not possible to send automatically by config
// CS: vytvoříme si interface, který nám pomůže formulář nainjectovat do presenteru
// musí mít právě jednu metodu create, která obsahuje parametry, jenž nejdou předat
// auotmaticky configem.
// více zde http://pla.nette.org/cs/create-components-with-autowiring
interface IFooFormFactory
{
/**
* @param $fooParam
* @return FooForm
*/
function create($fooParam);
}
<?php
class MyPresenter extends BasePresenter
{
// EN: inject the form interface into the presenter
// CS: nainjectujeme si rozhraní továrny formuláře
/** @var \IFooFormFactory @inject */
public $fooFormFactory;
// EN: this is our foo parameter we need to process our form (for some reason)
// CS: toto je náš vlastní parametr, který si z nějakého důvodu potřebujeme předat do formuláře pro zpracování hodnot
private $fooParam;
// EN: create the from in presenter
// CS: vytvoříme formulář v presenteru
protected function createComponentFooForm()
{
// EN: call create() method of the form with our foo parameter
// CS: zavoláme metodu create() formuláře a předáme náš parametr
$form = $this->fooFormFactory->create($this->fooParam);
// EN: this is the event, we defined in the form. Now we can hook on it stuff specific for this presenter, like
// redirect or redrawControl()
// CS: na událost, kterou jsme si ve formuláři definovali, a který se spustí po jeho odeslání a zpracování, navěsíme další
// potřebné věci. V tomto případě redirect. Ten je konkrétní pouze pro tento presenter, proto je uveden zde.
$form->onFormSuccess[] = function () {
$this->flashMessage('Form has been submitted successfuly', 'success');
$this->redirect('Redirect:somewhere');
};
return $form;
}
}
@vojtech-dobes
Copy link

  1. It's not magical. It follows your control (createComponentForm => component form). It can work with different name (createComponentForm2 => {form form2}).
  2. Snippet is basically function, and if it's invalidated, the rest of template isn't run at all. And because {input} and {label} macros rely on existence of $_form variable (which is initialized in {form} macro), they will fail if {form} isn't part of the snippet. So to enable that, you need to pass it to template manually.

@castamir
Copy link

Another shortcut:

public function render()
{
    $this->template->render(__DIR__ . '/NewTaskForm.latte');
}

@zraly
Copy link
Author

zraly commented Nov 10, 2014

Thanks, I see. I updated the code, so now it should be clear what is what.

@enumag
Copy link

enumag commented Feb 3, 2015

@Medhi I'd add $this->flashMessage() before the redirect. Most of the time you want to inform the user that the form was successfully processed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment