Last active
February 11, 2020 19:19
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# EN: we have to add the form interface into services | |
# CS: interface formuláře si přidáme do služeb | |
services: | |
- \IFooFormFactory |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{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} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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: Interensting. Two questions:
- Does it mean, that
form
is some special magical name? - Why it should be passed in a variable, if wrapped in a snippet?
- It's not magical. It follows your control (
createComponentForm
=> componentform
). It can work with different name (createComponentForm2
=>{form form2}
). - 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.
Another shortcut:
public function render()
{
$this->template->render(__DIR__ . '/NewTaskForm.latte');
}
Thanks, I see. I updated the code, so now it should be clear what is what.
@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
Just a note: I think you don't need to pass the
$form
variable into template, because you can use{form form}
there (passing not variable but name of component). But on the other hand, it's good to pass manually like this if you want to wrap part of the form's template in snippet :). So maybe that's better explanation why to pass that variable.