Formulář se nevykreslí při předání proměnné
- plasmo
- Člen | 66
Přes továrničku vytvářím formulář pro přidávání komentářů k článku. Potřebuji aby se do skrytého pole vždy uložila hodnota s id článku. Postup jsem udělal následující:
V presenteru:
public function createComponentAddKomentar($id)
{
$form = new AppForm;
$form->addText('jmeno','Jméno')
->addRule(AppForm::FILLED, 'Prosím zadejte jméno.');
$form->addHidden('clanek',$id);
$form->addSubmit('pridat', 'Přidat');
return $form;
}
V šabloně:
{widget addKomentar $vtip->id_vtip}
Pokud odstraním to předávání proměné, formulář se vypíše, takto ne. Kde může být chyba? Díky
Editoval plasmo (20. 10. 2010 12:37)
- srigi
- Nette Blogger | 558
Bohuzial tu premmenu si cez sablonu asi nepredas, viď Vykreslování komponent. Takze si to ID uloz niekam do presentera alebo modelu a napis to cca takto:
public function createComponentAddKomentar($name)
{
$form = new AppForm($this, $name);
$form->addText('jmeno','Jméno')
->addRule(AppForm::FILLED, 'Prosím zadejte jméno.');
$form->addHidden('clanek',$this->vtipId);
$form->addSubmit('pridat', 'Přidat');
// return $form; neni treba
}
Editoval srigi (20. 10. 2010 13:35)
- Vojtěch Dobeš
- Gold Partner | 1316
Pokud je článek na stránce jeden, určitě bude stačit někde v
action
nebo render
metodě zavolat:
$this['addKomentar']->setDefaultValues(array(
'clanek' => $idClanku,
));
V okamžiku $this['addKomentar']
se zavolá ta „tovární
metoda“ createComponentAddKomentar
a následné
setDefaultValues
nastaví hodnotu toho skrytého pole (které už
existuje) přímo v okamžiku, kdy máš to idéčko článku k dispozici.
Editoval vojtech.dobes (20. 10. 2010 15:40)
- plasmo
- Člen | 66
vojtech.dobes napsal(a):
Pokud je článek na stránce jeden, určitě bude stačit někde v
action
neborender
metodě zavolat:$this['addKomentar']->setDefaultValues(array( 'clanek' => $idClanku, ));
V okamžiku
$this['addKomentar']
se zavolá ta „tovární metoda“createComponentAddKomentar
a následnésetDefaultValues
nastaví hodnotu toho skrytého pole (které už existuje) přímo v okamžiku, kdy máš to idéčko článku k dispozici.
Děkuju za nakopnutí :) Tvůj kód mi to nevzalo, ale vyžeil jsem to následovně:
public function actionText($seo){
$this->detail = array("clanek"=>$seo); //$seo obsahuje hezkou adresu, též jednoznačnou
}
A do továrničky:
$form->setDefaults($this->detail);
- Vojtěch Dobeš
- Gold Partner | 1316
Omlouvám se, mělo to být samozřejmě setDefaults
(s tím to
bude fungovat určitě:).
- MaJJ
- Člen | 18
Zdravím,
jak tohle vyřešit, pokud je formulářů (těch {control …}) na stránce více, a ke každému bych potřeboval zavolat jiný argument?
Zkoušel jsem to vyřešit podobně jako na začátku plasmo, ale samozřejmě to nejde:
{block content}
{if count($tricka)}
{foreach $tricka as $tricko}
Název: {$tricko->nazev}<br>
{control trickoForm $tricko->id}
<br>
{/foreach}
{/if}
protected function createComponentTrickoForm($id_t)
{
$velikosti = TrickaModel::FetchSizes($id_t);
$barvy = TrickaModel::FetchColors($id_t);
$kod = TrickaModel::FetchCode($id_t);
$form = new AppForm();
$form->addHidden('kod', $kod);
$form->addText('kusu', 'Kusů:', 20, 5)
->addRule(AppForm::INTEGER, 'Počet kusů je povinný!');
$form->addSelect('velikost', 'Velikost:', $velikosti)
->addRule(AppForm::FILLED, 'Velikost je povinná!');
$form->addSelect('barva', 'Barva:', $barvy)
->addRule(AppForm::FILLED, 'Barva je povinná!');
$form->addSubmit('objednat', 'Objednat');
$form->onSubmit[] = array($this, 'trickoForm_onSubmit');
return $form;
}
public function trickoForm_onSubmit(Form $form)
{
$tricko = $form->getValues();
KosikModel::Insert($tricko);
$this->flashMessage('Úspěšně jste vložili tričko do košíku.');
$this->redirect('objednavka');
}
- Mikulas Dite
- Člen | 756
Jenom doplním, že parametry z {control $name $arguments}
jdou
do render()
metody.
- MaJJ
- Člen | 18
Still clueless … :)
Netuším, jestli jsem správně pochopil Vaška – do createComponentTrickoForm() to $id_t tedy nepatří … No – ale kam teda? :)
Mikuláši – do render() metody … tím myslíš do této?
$control->getWidget("cartControl")->render($tricko->id);
(https://latte.nette.org/cs/tags#…)
… Tu ale v presenteru nemůžu použít, ne? Nebo jsi myslel renderDefault()
v presenteru?
- Mikulas Dite
- Člen | 756
Jasně, myslím tu render metodu té konkrétní komponenty, tedy to cos psal
$control->getWidget("cartControl")->render($tricko->id);
je to samé jako {control trickoForm $tricko->id}
.
Ten argument pro {control $name, $argument}
je navíc u formu
pro tohle https://api.nette.org/…rer.php.html#133
Máš to zapeklitější o to, že potřebuješ ten formulář kvůli validaci naplnit i podruhé, po submitu (viz jak funguje formulář/kdy se proč tvoří a validace).
Po vytvoření formuláře přes něj iterovat nemůžeš (můžeš, ale bude to pořád stejné), takže si asi napiš nějakou plnohodnoutnou komponentu, která celý ten foreach zabalí. Nebo dej ten foreach už do té továrničky, rozděl to na groupy a hezky to vyrenderuj. Čisté řešení teď nevymyslím.
- MaJJ
- Člen | 18
Ha, možná jsem našel řešení… https://forum.nette.org/…zeni-smazani
Každopádně díky moc!
Edit: ikdyž vlastně asi ne … safra. :D
Edit2: ještě pár related linků, které by se mohly hodit lidem se stejným problémem:
https://forum.nette.org/…tu-do-kosiku
https://forum.nette.org/…louzi-widget
https://forum.nette.org/…atecomponent
Editoval MaJJ (17. 11. 2010 1:01)
- Ani
- Člen | 226
Tu komponentu na tričko si vytvoř jako samostatnou třídu dědící od Control. V ní tu funkci render($id_t).
<?php
class Shirt extends Control {
private $id_t;
protected function createComponentTrickoForm() {
$velikosti = TrickaModel::FetchSizes($this->id_t);
$form = new AppForm();
//.......
return $form;
}
public function trickoForm_onSubmit(Form $form){}
public function render($id_t){
$this->id_t = $id_t;
}
}
?>
Editoval Ani (16. 11. 2010 23:17)
- MaJJ
- Člen | 18
Mně už to dneska nemyslí … :D Prosímtě, jak to mám pospojovat? Určitě mně něco chybí asi v tom TrickaPresenteru – ale už nejsem schopný vymyslet, co… :)
Někde bude možná volání new Tricka
nebo
Tricka::createComponentTrickoForm()
nebo tak něco? Achjo. :D
class Tricka extends Nette\Application\Control
{
private $id_t;
public function createComponentTrickoForm() {
$velikosti = TrickaModel::FetchSizes($id_t);
// (...)
$form = new AppForm($this,$name);
// (...)
return $form;
}
public function trickoForm_onSubmit(Form $form)
{
$tricko = $form->getValues();
KosikModel::Insert($tricko);
$this->flashMessage('Úspěšně jste vložili tričko do košíku.');
$this->redirect('objednavka');
}
public function render($id_t)
{
$this->id_t = $id_t;
}
}
class TrickaPresenter extends BasePresenter
{
// (...)
public function createComponentTrickoForm()
{
}
public function trickoForm_onSubmit(Form $form)
{
}
}
- Ani
- Člen | 226
V tom trička presenteru si už nevytváříš ten formulář, ale tu tvojí komponentu, takže tam přidej metodu (tu metodu na formulář můžeš z presenteru odstranit).
<?php
public function createComponentTricko(){
$tricko = new Tricko;
return $tricko;
}
?>
V šabloně pak v té iteraci zavoláš:
{control tricko $tricko->id}
Jo a aby se ti ten formulář vykreslil, tak doplň do té render metody Tricka to echo.
<?php
public function render($id_t)
{
$this->id_t = $id_t;
echo $this['trickoForm'];
}
?>
Ono pochopit ze záčátku jak fungují komponenty je trochu náročnější. Já jsem taky tápal přesně na tomhle. Dúležitý je vědět, že komponenta je ta třída dědící od Control a ne ta metoda creatComponent, ta ji jen vytvoří.
Editoval Ani (17. 11. 2010 0:33)
- MaJJ
- Člen | 18
Díky za pomoc, teď už to běží líp, ale ještě jedna věc mi tam hapruje. Každý další formulář má ty samá data jako ten první. Přijde mi, že se ta komponenta prostě vykreslí jen jednou, dosadí se do ní hodnoty, atd, atd, ale při dalších voláních toho {control …} už se ji to nesnaží udělat znovu. Což bych právěže potřeboval :D Na základě toho argumentu v {control …} měnit obsah formuláře.
- MaJJ
- Člen | 18
Hmm. Tak nový problém. :D To, že se vykresloval pořád jen jeden formulář, jsem nakonec vyřešil takto:
<?php
use Nette\Application\AppForm;
class TrickaPresenter extends BasePresenter
{
// (...)
public function getForm($id_t)
{
$velikosti = TrickaModel::FetchSizes($id_t);
// (...)
$form = new AppForm($this, "trickoForm" . $id_t);
// (...)
$form->onSubmit[] = array($this, 'formSubmit');
return $form;
}
public function formSubmit(AppForm $form)
{
$tricko = $form->getValues();
KosikModel::Insert($tricko);
$this->flashMessage("Úspěšně jste přidali tričko do košíku!");
$this->redirect('this');
}
// (...)
}
a v šabloně volám:
{$presenter->getForm($tricko->id)}
JENŽE. Sice se všecko vykreslí dobře, ale když některý z formulářů odešlu, vyhodí mně to tuhle výjimku:
(samozřejmě číslo u ‚trickoForm‘ se mění podle toho, který formulář odešlu)
Nette\Application\BadSignalException #403
The signal receiver component 'trickoForm1' is not found.
A já se ptám, jak nastavit to onSubmit[], aby mně to z každého formuláře vždycky zavolalo tu metodu formSubmit (a fungovalo to. :D )…
Ono to potřebuje, aby to byla komponenta? Změní se něco, když to
udělám jako Form a ne jako AppForm? Zkoušel jsem to (přičemž před
return $form;
jsem strčil if isSubmitted()), ale zadrhl jsem se na
tom, že jsem nemohl udělat $this->redirect('this')
, protože
už se stihlo něco vypsat…
- MaJJ
- Člen | 18
OK, konečně vyřešeno – díky tady tomuhle postu …
Vypadá to nyní (osekáno o zbytečnosti) nějak takhle:
Presenter
<?php
use Nette\Application\AppForm;
class TrickaPresenter extends BasePresenter
{
// (...)
public function createComponent($name)
{
if(preg_match("#^trickoForm(\d+)$#", $name, $matches)) {
$id_t = $matches[1];
$this->createInstanceTrickoForm($name, $id_t);
}
parent::createComponent($name);
}
protected function createInstanceTrickoForm($name, $id_t)
{
$velikosti = TrickaModel::FetchSizes($id_t);
// (...)
$form = new AppForm($this, $name);
$form->addHidden('kod', $kod);
// (...)
$form->addSubmit('objednat', 'Objednat');
$that = $this;
$form['objednat']->onClick[] = function(Nette\Forms\ISubmitterControl $button) use ($that, $id_t)
{
$tricko = $button->getForm()->getValues();
//KosikModel::Insert($tricko);
$that->flashMessage('Úspěšně jste vložili tričko do košíku.');
$that->flashMessage('Kód: ' . $tricko['kod']);
};
$form->onSubmit[] = function(AppForm $form) use ($that) {
$that->redirect('this');
};
return $form;
}
}
View
{foreach $tricka as $tricko}
Název: {$tricko->nazev}<br>
<!-- ... -->
{control 'trickoForm'.$tricko->id}<br>
{/foreach}
Některé věci jsou pro mě pořád španělskou vesnicí, ale na to časem přijdu :) Hodně jsem se při řešení tohoto problému naučil :D Takže díky všem.