Formulář jako komponenta a DI
- admin@easyweb4u.cz
- Backer | 146
Vytvořil jsem si komponentu formuláře App/Forms/TherapyForm.php, přes presenter ji posílám do šablony. Vše funguje, až na to, že do té komponenty chci injektovat službu /** @var \App\Model\TherapyService @inject */, kterou normálně používám v jiném presenteru. V komponentě App/Forms/TherapyForm.php to ale hlásí chybu: Call to a member function getTimeSelect() on null. Jak na to?
- admin@easyweb4u.cz
- Backer | 146
<?php
namespace App\Forms;
use Nette;
use Nette\Application\UI;
class TherapyForm
{
/** @var Nette\Database\Context */
private $database;
/** @var \App\Model\TherapyService @inject */
public $therapy;
public function __construct(Nette\Database\Context $database) {
$this->database = $database;
}
public function create($id)
{
$form = new UI\Form;
....
?>
- David Matějka
- Moderator | 6445
@inject anotace funguje defaultne pouze v presenterech, jinde zavislosti predavej pres konstruktor (stejne jako to delas s databazi)
- admin@easyweb4u.cz
- Backer | 146
Přejmenováno, funguje.
<?php
namespace App\Forms;
use Nette;
use Nette\Application\UI;
use App\Model;
class TherapyFormFactory
{
/** @var Nette\Database\Context */
private $database;
/** @var Model\TherapyService */
private $therapyService;
public function __construct(Nette\Database\Context $database, Model\TherapyService $service) {
$this->database = $database;
$this->therapyService = $service;
}
?>
- h4kuna
- Backer | 740
Taky by bylo optimální, aby jsi si udělal Factory na Form a tuto továrnu poslal přes kontruktor TherapyFormFactory.
A namísto
$form = new UI\Form;
dělat
$form = $this->formFactory->create();
Do budoucna ti to umožní:
- globálně přidat překladač
- mít více metod, třeba s aktivovaným csrf a bez něj, get vs post atd
- když použiješ FormFactory tak v ní můžeš teprve navěsit Extension methods, pomocí Utils\ObjectMixin::setExtensionMethod a není potřeba to dělat v requestech kde nejsou formuláře
EDIT: Stejně jako je v sanboxu
Editoval h4kuna (9. 11. 2018 11:06)
- admin@easyweb4u.cz
- Backer | 146
To je všechno pěkné, ale teď jsem se zasekl na následujícím:
V presenteru mám:
<?php
protected function createComponentTherapyForm()
{
$form = $this->therapyFormFactory->create($this->id);
$form->onSuccess[] = function (UI\Form $form) {
};
return $form;
?>
posílám z presenteru do formulářové komponenty parametr $this->id, abych do formuláře mohl načíst defaultní hodnoty.
<?php
public function create($id)
{
$form = new UI\Form;
$form->addProtection();
$row = $this->database->table('calendar')->get($id);
...
$form->addSubmit('send', 'Odeslat')
->setAttribute('class', 'btn btn-success');
$form->getElementPrototype()->class('ajax');
$form->onSuccess[] = [$this, 'processTherapyForm'];
return $form;
}
?>
(Formulář se má odeslat přes AJAX)
Formulář se načte, ale po odeslání se objeví noticka Trying to get property ‚day‘ of non-object, do dotazu se načte id = 0. Při znovunačtení formuláře už se nepřenese z presenteru $id. Zkoušel jsem to přes konstruktor, ale zatím se mi nic nedaří…
PS: pokud formulář mám normálně v presenteru, vše funguje jak má
- admin@easyweb4u.cz
- Backer | 146
h4kuna napsal(a):
A ten ajaxový request (konkrétně url) vypadá jak?
No na tohle asi neumím odpovědět … url requestu …
localhost/projekt/calendar/default/1/10
to je poslední url po odeslání toho formuláře (id = 10)
Editoval admin@easyweb4u.cz (9. 11. 2018 14:40)
- admin@easyweb4u.cz
- Backer | 146
David Matějka napsal(a):
jak vypada presenter? konkretne cast, kde pracujes s tim
id
?
<?php
namespace App\Presenters;
use Nette\Application\UI;
class CalendarPresenter extends BasePresenter {
/** @var \App\Model\CalendarService @inject */
public $calendar;
/** @var \App\Forms\TherapyFormFactory @inject */
public $therapyFormFactory;
/** @var int */
public $id;
public function startup() {
parent::startup();
$id = intval($this->request->getParameter('id'));
$this->id = $id;
....
}
protected function createComponentTherapyForm()
{
$form = $this->therapyFormFactory->create($this->id);
$form->onSuccess[] = function (UI\Form $form) {
//$this->redirect('this');
};
return $form;
}
public function renderDefault() {
$this->template->id = $this->id;
}
?>
Ale jak jsem psal to řešení, pokud je v presenteru normálně funguje. Přes komponentu to řeším kvůli vícero použití.
- h4kuna
- Backer | 740
admin@easyweb4u.cz napsal(a):
No na tohle asi neumím odpovědět … url requestu …
localhost/projekt/calendar/default/1/10
To jsi vyčetl z konsole nebo jsi odhadl? Opravdu to ověř, že to tak je. V chrome zmačkni f12 záložka Network a když vyvoláš ajaxový požadavek ukáže se ti url. Případně si můžeš udělat dump toho id a vypíše se ti jako odpověď ze servru.
Jelikož id není persistentní, není uvedený ani v render metodě, tak si myslím že se nedostane do atributu action v tagu form, tzn. prostě se ti ztratí z požadavku.
Pokud to tak je, tak by mělo pomoci
class CalendarPresenter extends BasePresenter {
/**
* @var int
* @persistent
*/
public $id;
}
nebo
public function renderDefault($id) {
$this->template->id = $this->id;
}
Dokumentace k persistentním parametrům
Editoval h4kuna (9. 11. 2018 15:34)