how to pass data from createComponent totemplate in Version 3.0?
- thcom
- Backer | 94
Hi, simple form example
presenter:
<?php
protected function createComponentTestForm() {
$this->template->test = 'KozelX';
$testForm = new UI\Form;
$testForm->addText('osel', '');
$testForm ->addSubmit('save', 'uložit');
$testForm->onSuccess[] = [$this, 'TestFormSucceeded'];
return $testForm ;
}
?>
template:
{block content}
DUMPTEST >{$test}<
{control testForm }
{/block}
in version 3.0 i get
Notice – Undefined variable: test
in version 2.4 i can see KozelX text
please help me, how to pass variables to template
many thanks
- teekey99
- Member | 45
You're trying to render $test
variable before it is assigned to
template. It's because your createComponentTestForm
method is
called with {control testForm}
in the template, which happens
after DUMPTEST >{$test}<
.
Assign the $test
variable in action
or
render
method, not in createComponent
.
- Marek Bartoš
- Nette Blogger | 1264
Imho nothing changed in 3.0 in components creation.
createComponent*
method is called first time it's used. When form
is sent then latest moment is in handle*
call stage, when form is
rendered it's in template. In case it's first time used in template is
template variable assignment done too late. That's why you should do only stuff
directly related to component in createComponent* methods. But you can also
initialize component sooner, just by calling $this['testForm']
,
e.g. in beforeRender()
- teekey99
- Member | 45
thcom wrote:
thank you
in version 2.4 it was workingand i need pass variable from create component, because i create special desing of form save it to an array and i render page design from this array
thank You
In that case I would suggest wrapping this all in a component that can handle both the form and the design you need for it.
- thcom
- Backer | 94
hi, i try to study
pla.nette.org/cs/best-practise-formulare-jako-komponenty
i am able to create a form with a factory
but when i tray wrap the form in UI\Control i have a problem with attaching this component to presenter
i get message Component of type ‘App\Forms\TranslateFormFactory’ is not attached to ‘Nette\Application\UI\Presenter’
component:
<?php
class TranslateFormFactory extends UI\Control {
private $database;
public function __construct(Nette\Database\Connection $database) {
$this->database = $database;
}
protected function attached($presenter): void {
parent::attached($presenter);
}
public function create() {
$form = new UI\Form;
// mohu použít $this->database
$form->addText('vosel', 'KozelX');
$form->addSubmit('send', 'Odeslat');
$form->onSuccess[] = [$this, 'processForm'];
$this->template->kozel = 'Vosel';
return $form;
}
public function processForm($form) {
dump($form->values); exit;
}
}
/** rozhranní pro generovanou továrničku */
interface ITranslateFormFactory {
/** @return TranslateFormFactory */
function create();
}
?>
and presenter:
<?php
final class HomepagePresenter extends BasePresenter {
/** @var Forms\TranslateFormFactory @inject */
public $translateFormFactory;
protected function createComponentTranslateForm() {
$control = $this->translateFormFactory->create();
$control->onSuccess[] = function (UI\Form $form) {
$this->redirect('this');
};
return $control;
}
}
?>
i am not sure, if i undestand the section with onCategorySave() method
thank you !!
- CZechBoY
- Member | 3608
Rename create
in form factory (TranslateFormFactory) to
createComponentForm
and rename the class itself to not contain
factory
– as it is not factory but control/component (this is
not required by nette but is better to undestand what is that class).
Also remove attached method (it is useless).
In presenter inject that interface generated factory and call that in
createComponentTranslateForm. You can find your form in
$control['form']
, where form is the name of component in
TranslateFormControl (the text after createComponentForm
).
Sorry for not pasting code, i’m on mobile :-(.
- teekey99
- Member | 45
You're probably misunderstanding the concepts of Control
components and their factory interfaces.
Control component allows you to create re-usable parts of your application.
Same as presenter, it provides you with core functionalities of
nette/component-model
. Each presenter is basically a component too.
Control is an isolated pice of UI, that can be easily rendered in any presenter.
The factory interface takes the role of a service in Dependency Injection
Container where Nette uses its create
method to create an
instance of your component.
So if I have a component MyComponent
and a factory interface
MyComponentFactory
, then Nette de-facto calls
new MyComponent()
while implementing the factory's
create
method. The component class itself don't
have to have the create
method.
Then, inside the component, you can create and attach other components (also forms), make redirects, create and handle signals etc.
Reviewing your code, it should look something like this:
FormWrapper.php
class FormWrapper extends UI\Control
{
private $database;
public function __construct(Nette\Database\Connection $database)
{
$this->database = $database;
}
public function render()
{
$this->template->kozel = 'Vosel';
$this->template->render(__DIR__ . '/templates/formWrapper.latte')
}
protected function createComponentForm()
{
$form = new UI\Form;
$form->addText('vosel', 'KozelX');
$form->addSubmit('send', 'Odeslat');
$form->onSuccess[] = [$this, 'processForm'];
return $form;
}
public function processForm($form)
{
bdump($form->values);
$this->presenter->redirect('this');
}
}
templates/formWrapper.latte
In component template, you render UI\Form
.
{control form}
FormWrapperFactory.php
interface FormWrapperFactory
{
/**
* @return FormWrapper
*/
public function create();
}
HomepagePresenter.php
final class HomepagePresenter extends BasePresenter
{
/** @var FormWrapperFactory @inject */
public $formWrapperFactory;
protected function createComponentFormWrapper()
{
return $this->formWrapperFactory->create();
}
}
templates/Homepage/default.latte
In presenter template you render UI\Control
which wraps and
renders UI\Form
created inside of it.
{block content}
{control formWrapper}
For further info, please refer to components docs.
Last edited by teekey99 (2019-12-19 23:47)
- teekey99
- Member | 45
Oh BTW, since you're asking about Nette 3.0, it supports latest version of PHP so you can make use of advanced type hints (typed properties, strict return types etc.). Much better than just annotations, meaning you can for example do:
interface MyComponentFactory
{
public function create(): MyComponent;
}
Last edited by teekey99 (2019-12-19 23:52)
- thcom
- Backer | 94
perfect !
many thanks for ypour help
now i have a little knowledge about factories i try some modifications and it clear
but last (I HOPE) questuion is
how to pass parameters to a form ?
for example i have form with some table rows nazev_cz and nazev_en
and i need to call form with parameter $tb_name
in template
{control translateForm, $tb_name}
is thos right way and where can i this parameter catch ?
thank you !!
- CZechBoY
- Member | 3608
Better is to create component with this parameter (in presenter/component)
rather than call in parametrised in template.
But if you really want it you can call it in template as you wrote
({control translateForm, $tb_name}
) and in
FormWrapper::render
accept this parameter:
public function render($tb_name)
{
$this->template->kozel = 'Vosel';
$this->template->tb_name = $tb_name;
$this->template->render(__DIR__ . '/templates/formWrapper.latte');
}
btw name of that parameter in method render is on you, Nette pass it as positional parameters (not named).
Last edited by CZechBoY (2019-12-20 15:42)