Vytvoření a zpracování dynamického formuláře
- Musilda
- Člen | 12
Mám začátečnický dotaz na vytvoření formuláře. Mohu vytvořit formulář tak, že vytvořím jen „obálku“, tady definuji jen form a submit
protected function createComponentVybermestaForm()
{
$form = new Form();
$form->addSubmit('create', 'Nastavit')
->setAttribute('class', 'ulozit');
$form->onSuccess[] = callback($this, 'vybranoFormSubmitted');
return $form;
}
a v render vytvořím pole hodnot
public function render()
{
$i=1;
foreach($this->mesta as $m){
$mesta[$i]['id']=$m['id'];
$mesta[$i]['name']=$m['name'];
$i++;
}
$this->template->mesta = $mesta;
$this->template->setFile(__DIR__ . '/Mesta.latte');
$this->template->render();
}
S tím, že to v šabloně jen složím?
{form vybermestaForm}
{foreach $mesta as $mesto}
{first}<table>{/first}
{first 4}<tr>{/first}
<td><input type="checkbox" name="{$mesto['name']}" value="{$mesto['id']}">{$mesto['name']}</td>
{last 4}</tr>{/last}
{last}</table>{/last}
{/foreach}
{input create}
{/form}
Nebo ty checkboxy musím vytvářet ve formuláři?
Jde mi o to, že nevím, kolik položek je v databázi. Zkusil jsem to takto,
ale po odeslání formuláře se nic nestane. Potřebuji, aby se vytvářela
sessions a bohužel se mi to nedaří.
public function vybranoFormSubmitted(Form $form)
{
foreach ($form->values as $mes => $me ){
$section = $this->section;
$section->$mes = 'ok';
}
$this->flashMessage('Zkouška', 'success');
$this->redirect('this');
}
Ani flashMessage se nezobrazí. Toto vše mám v komponentě, ne v presenteru, ale vykreslování funguje bez problému. Teď ale nevím, zda nedělám chybu při vytváření a odeslání formuláře, nebo je někde zakopán pes v tom, že to není v presenteru. Budu vděčný za každou pomoc.
- JakubJarabica
- Gold Partner | 184
Formulár ked už, tak doupravuj v action. Pri submite sa totiž musi zložiť už v action, render fáza je az po spracovaní signálov. Údaje na vytvorenie formu si môžeš vytiahnuť aj vo factory metóde(parametre presenteru sú v $this->params). Tak získaš aj lazy loading(v actione ho vytvoríš a v šablóne ho nemusíš vykresliť).
- llook
- Člen | 407
Takhle se to udělat nedá. Formuláře v Nette berou v potaz pouze pole, která jsou definovaná a v momentě kdy se provádí onSuccess máš definovaný pouze ten submit.
Ani kdybys ta pole opravdu definoval v té šabloně (přes $form->addCheckbox), tak by to nefungovalo, protože onSuccess se provádí před renderem a tedy před zpracováním šablony.
Zkrátka si ten formulář nadefinuj celý v té továrničce createComponentVybermestaForm, nějak takhle:
protected function createComponentVybermestaForm()
{
$form = new Form();
$form->addSubmit('create', 'Nastavit')
->setAttribute('class', 'ulozit');
$form->onSuccess[] = callback($this, 'vybranoFormSubmitted');
$form->addGroup('mesta');
foreach($this->mesta as $m){
$form->addCheckbox($mesta['id'], $mesta['name']);
}
return $form;
}
A v šabloně ho vykreslíš nějak takhle:
{? $form = $control['vybermestaForm']}
{form $form}
<ul n:if="$form->errors" class="errors">
<li n:foreach="$form->errors as $error">{$error}</li>
</ul>
<table>
{foreach $form->groups['mesta'] as $name => $field}
{first 4}<tr>{/first}
<td>{input $name} {label $name /}</td>
{last 4}<tr>{/last}
{/foreach}
</table>
{input create}
{/form}
- uestla
- Backer | 799
(Možná jen přepíšu to, co psal přede mnou JAM3SoN [edit] a llook [/edit], ale přece:)
Jednak nemáš formulář dodefinován, ale bokem mimo Nette si vytváříš inputy ručně v šabloně – to samo už není dobré a Nette pak nemá odkud získat hodnoty.
Druhak by to chtělo v místě, kde předáváš pole $mesta
komponentě (tedy např. v továrničce na komponentu někde v nadřazené
komponentě (např. presenteru)), rovnou sestavit formulář, čili ty checkboxy
vytvořit – nejlépe do containeru.
A za třeťak se mi nezdá kód, cos poslal, je nějaký upravovaný asi. Na
to, co děláš tak složitě v iteraci, existuje funkce
array_values()
.
Možné řešení:
// presenter:
protected function createComponentCities()
{
$cities = new CitiesControl;
$cities->setCities( Model::getCitiesList() );
return $cities;
}
// CitiesControl:
function setCities(array $cities)
{
$this->cities = array_values($cities);
}
protected function createComponentCitiesForm()
{
$form = new UI\Form;
$container = $form->addContainer('cities');
foreach ($this->cities as $city) {
$container->addCheckbox($city['id'], $city['name']);
}
$form->addSubmit('create', 'Nastavit');
// onSuccess ...
return $form;
}
šablona komponenty:
{control citiesForm}
PS: ohledně té nezobrazené flashMessage – zdálo by se na první
pohled, že se nedetekovalo odeslání formuláře, nicméně to by se dle mého
detekovat mělo. Problém nejspíš bude v tom, že nikde v šabloně
komponenty, ve které tu flashMessage vytváříš, flash messages
nevykresluješ. Buď je vykresluj v komponentě, nebo je vytvářej pro
presenter ($this->presenter->flashMessage()
).
Editoval uestla (9. 6. 2012 9:07)
- zimmi
- Člen | 94
@llook zkouším naplnit formulář tak, jak jsi psal, tj. v cyklu foreach. Plním ho z proměnné $this->rivers, která je výsledkem dotazu do DB. Když si však po proběhnutí cyklu dumpnu formulář, zjistím, že neobsahuje žádné komponenty, ačkoliv $this->rivers obsahuje přesně to, co obsahovat má. Plnění formuláře vypadá takto:
protected function createComponentExportForm()
{
//Debugger:dump($this->rivers);
$form = new AppForm;
$form->onSuccess[] = callback($this, 'exportFormSent');
foreach ($this->rivers as $r) {
$idvt = (int)$r->idvt;
$form->addCheckbox('c_'.$idvt, 'c_'.$idvt);
}
return $form;
}