Super továrnička + widget + editační formulář
- Patrik Votoček
- Člen | 2221
Nevíte někdo jak elegantně zkombinovat novou super továrníčku, widget a editační formulář. Už jsem zde psal že předělávám celou appsku na novou super továrničku a widget ale mám jeden problém. Jak na editační formulář?
Do teď:
class MyPresenter extends BasePresenter
{
public function actionEdit($id)
{
$form = new AppForm($this, 'editForm');
$form->addText('value', "Value: ");
$form->addSubmit('sub', "Save");
$form->onSubmit[] = array($this, 'editFormSubmitted');
$model = new Model();
$data = $model->getById($id);
$form->setValues($data); //zjednodušeně
$this->template->form = $form;
}
}
{!$form}
S příchodem Super Továrničky se snažím všechno předělat do
createComponentEditForm($name);
a v šabloně používat
{control editForm}
. Ale je tu problém jak dostat do
formuláře aktuální data? Protože metodě
createComponentEditForm($name);
nemám jak předat id
editovaného prvku nebo data. Jediné řešení které mě zatím
napadlo je nepoužívat widget a dělat to takto:
class MyPresenter extends BasePresenter
{
public function createComponentEditForm($name)
{
$form = new AppForm($this, $name);
$form->addText('value', "Value: ");
$form->addSubmit('sub', "Save");
$form->onSubmit[] = array($this, 'editFormSubmitted');
}
public function actionEdit($id)
{
$form = $this->getComponent('editForm');
$model = new Model();
$data = $model->getById($id);
$form->setValues($data); //zjednodušeně
$this->template->form = $form;
}
}
{!form}
A tak se ptám jde tohle něják řešit abych mohl
i u editačního formuláře používat
{control editForm}
?
- Ondřej Brejla
- Člen | 746
Já normálně používám {control form}, tobě to hází nějaké chyby či co?
Můj kód vypadá nějak takto:
protected function createComponentForm($name) {
$form = new MyAppForm($this, $name);
$form->add...;
$form->addSubmit('insert', 'Vložit');
}
public function actionEdit($id) {
$form = $this->getComponent('form');
$smth = $this->model->getSmth($id);
$form->setDefaults(array(
...
));
$form->onSubmit[] = array($this, 'editFormSubmitted');
$this->setView('form');
}
A normálně funguju…(setView() používám, protože používám jeden form pro edit i insert…)
- Patrik Votoček
- Člen | 2221
Tak to je super jestli to funguje i s naplněním dat. Mě se nepozdávalo
to $form = $this->getComponent('form');
v action. (Nebyl jsem
si jist jestli dojde k naplnění dat v action když volám widget. díky
Editoval vrtak-cz (9. 8. 2009 14:53)
- vlki
- Člen | 218
Myslím, že to byl PetrP, u kterého jsem to v nějakém příspěvku
viděl. Pokud je potřeba pro vytvoření komponenty nějaký parametr, nebát
se použít metodu getParam
. Osobně mi to přijde i tak nějak
čistější.
class MyPresenter extends BasePresenter
{
public function createComponentEditForm($name)
{
$form = new AppForm($this, $name);
$form->addText('value', "Value: ");
$form->addSubmit('sub', "Save");
$model = new Model();
$data = $model->getById($this->getParam('id'));
$form->setValues($data); //zjednodušeně
$form->onSubmit[] = array($this, 'editFormSubmitted');
}
public function actionEdit($id)
{
}
}
vrtak-cz napsal(a):
Tak to je super jestli to funguje i s naplněním dat. Mě se nepozdávalo to
$form = $this->getComponent('form');
v action. (Nebyl jsem si jist jestly dojde k naplnění dat v action když volám widget. díky
Dojde, protože si aplikace projde tou action částí. Pokud bys tam akcí
ale měl víc a v některé bys v rámci následného view použil
{control editForm}
, tak by ses pak mohl divit.
- David Grudl
- Nette Core | 8218
Vyčlenit naplnění dat do metody actionEdit je určitě správný
přístup. I tak můžeš použít v šabloně
{control editForm}
. Takže actionEdit může vypadat i takto:
public function actionEdit($id)
{
$model = new Model();
$data = $model->getById($id);
$this['editForm']->setDefaults($data);
}
- Sqdw
- Člen | 3
Zkoušel jsem použít Davidovu verzi a obávám se, že to úplně nešlape.
Widget se zobrazí jedině pokud v metodě createComponentMyForm
použiju return $form
, jenže i když potom použiju metodu
setDefaults
, tak formulář se pochopitelně zobrazí prázný…
Dá se to vyřešit nějak jinak, abych mohl použít
{control myForm}
?
Editoval Sqdw (11. 1. 2010 15:48)
- setka
- Člen | 10
V souvislosti s tímhle bych se chtěl zeptat na jednu věc:
Vyčlenit naplnění dat do metody actionEdit je určitě správný přístup. I tak můžeš použít v šabloně {control editForm}. Takže actionEdit může vypadat i takto…
Co jsem zkoušel, tak Action se volá ještě před obsluhou signálů, a to i signálů z komponent. Dejme tomu, že mám ve stránce např. komponentu – anketu. Hlasování v anketě je řešeno jako signál, potud vše funguje výborně.
Navíc ale hlasování v anketě realizuji AJAXem (používám jQuery řešení v podstatě totožné s tím přímo z Nette, nepoužívám mechanismus snippetů – obsluha signálu nastaví payload a volá terminate()) – jako asynchronní request na signál té komponety. V tomto případě se úplně zbytečně v Action volá model (třeba načtení dat z databáze), který třeba plní nějaký formulář ve stránce.
Napadlo mě plnit formulář daty z modelu až v Render metodě, mohou s tím být nějaké problémy? Pak mi z toho ale vychází, že Action bych využíval jen a pouze na případné přesměrování.
- Sqdw
- Člen | 3
Ondřej Mirtes napsal(a):
Sqdw: Ukaž kód, mělo by to rozhodně fungovat.
<?php
protected function createComponentArticleEditForm()
{
$form = new AppForm;
...
return $form;
}
public function actionEdit($articleId) {
$article = ArticleManager::getArticle($articleId);
$this['articleEditForm']->setDefaults(get_object_vars($article));
}
?>
A v šabloně potom:
{control articleEditForm}
Když dám Debug::dump($this['articleEditForm']);
v
actionEdit
, tak tam ty data jsou, ve widgetu se nezobrazí, raději
se ale ještě mrknu, jestli nemám starou verzi Nette…
- Ondřej Mirtes
- Člen | 1536
A vrací ten konstrukt get_object_vars($article)
pole, jaké
metoda setDefaults požaduje?
- MzK
- Člen | 127
Mám trochu podobný problém.. V šabloně mám
<h2>$article-name</h2>... atd.{control form1}
A do toho widgetu chci použít parametr $article->id
aby se
komentář vložil ke správnému článku.
{control form1($article->id)}
nejde,
ani {control form1 $article->id}
..
řešení
nechci používat → zbytečný SQL dotaz pro ID článku, když už jednou
proběhl pro výpis článků.
Ostatně stejný parametr jsem již v té samé šabloně použil pro výpis
článků takto:
{foreach $presenter->getComments($article->id) as $comment}
<p>{$comment->text}</p>
{/foreach}
Jak tedy použít u továrničky parametr ze šablony?
Editoval zacatecnik (20. 1. 2010 12:52)
- Ondřej Mirtes
- Člen | 1536
Vytáhni si to ID v odesílací metodě formuláře přes $this->getParam(‚id‘) (kde id je název parametru z nějaké renderArticle metody) a pracuj s ním tam – předávat ho formuláři při renderování je pozdě…
- Ondřej Mirtes
- Člen | 1536
Tak si to pak podle toho vyhledej přes dva dotazy :) A pokud ten dotaz v Presenteru už provádíš, tak ho přesunň do action* (protože v render* bylo už pozdě a odesílací metoda by o něm nevěděla) a nacachuj si ho do vlastnosti objektu, ať ho nemusíš provádět dvakrát. Nebo to nech na starost modelu…
- MzK
- Člen | 127
Už jsem to udělal takto:
<?php
public function renderArticle($url) { // vypise jeden clanek.
$model = new ArticlesModel;
$data = $this->template->article = $model->getArticle($url);
**$this->text_id = (int) $data['id'];** //timto ulozim do tridy
}
?>
A pak ve createComponentForm1
jenom dam
->value = $this->text_id;
Funguje to. Ale ptám se, e na tomto přístupu něco špatně?
Editoval zacatecnik (20. 1. 2010 16:10)
- Ondřej Mirtes
- Člen | 1536
Je to špatně – protože může nastat situace, kdy se ti komponenta
vytvoří dřív než nastane renderArticle fáze a $this->text_id budeš
mít prázdné. Proto bych to přesunul do
actionArticle($url);
.