měnitelný počet formulářových elementů
- vladimir
- Člen | 11
Já bych to asi řešil nějak takhle, přes Sessions. Podle hodnoty v selectboxu bych vytvoril dodatecna policka formulare, a v sessions bych si pamatoval predchozi obsah, aby kdyz uzivatel prihodi vic radku, predchozi data nezmizela. Ale jelikoz s Nette si hraju teprv chvili, tak to je mozna uplne zcestny reseni a rad se poucim jak lepe to resit :-)
MujPresenter.php
<?php
public function renderAdd($active = false)
{
$session = $this->session->getSection('mySess');
if ($active != true)
{
// pokud kreslim formular poprve, smazu si session z minula
$session->remove();
}
else
{
//pokud naopak jen upravuju pocet inputu, naplnim predchozi hodnoty ze session
if (isset($session))
{
$this['myForm']->setDefaults($session->form);
}
}
}
public function createComponentMyForm($name)
{
$session = $this->session->getSection("mySess");
$rows = (isset($session->form['rows'])) ? $session->form['rows'] : 2; //def je 2
$form = new Nette\Application\UI\Form;
$ints = array(); //nejak naplnit selectbox
for($i = 0; $i < 10; $i++)
{
$ints[$i] = $i;
}
$form->addSelect('rows', "Textboxů:", $ints)->setDefaultValue($rows);
$form->addSubmit("submit", "Vytvořit textboxy")
->setValidationScope(NULL)
->onClick[] = callback($this, "fillTextboxs");
$textboxs = $form->addContainer('textboxs');
for ($i = 1; $i <= $rows; $i++)
{
$sec = $textboxs->addContainer($i);
$sec->addText('inp', 'Input ' . $i . ':');
}
return $form;
}
public function fillTextboxs()
{
// zapamatuju si co bylo ve formulari
$session = $this->session->getSection('mySess');
$session->form = $this['myForm']->getValues();
// a uzivatele presmeruju na formular s novym poctem inputu
$this->redirect('this', array('active' => TRUE));
}
?>
add.latte
{control myForm}
- Ot@s
- Backer | 476
Psano z hlavy… Nezapomnět zaregistrovat addDynamic dle návodu.
$form = new Nette\Application\UI\Form;
// vyber poctu
$form->addSelect('count', 'Pocet', range(1,10) )->addRule(Nette\Application\UI\Form::FILLED, 'Zvolte pocet...');
if ($form->isSubmitted()) {
// jméno, továrnička, výchozí počet
$replicator = $form->addDynamic('textFields', function (Container $container) {
$i = (int) $container->getName();
$container->addText('text', 'Textbox c. '.$i);
}, $form['count']->getValue() );
$form->addSubmit('save', 'Ulozit obsah textboxu')
->onClick[] = callback($this, 'saveResult');
} else {
$form->addSubmit('show', 'Zobraz textboxy');
}
return $form;
Editoval Ot@s (14. 10. 2011 9:35)
- colek
- Člen | 59
Tak tohle se mi nepodařilo rozchodit, ale nakonec jsem si uvědomil, že v tom hledám asi zbytečnou složitost…
co takhle?
$form->addText('age0', 'Věk osoby č. 1');
if ($form->isSubmitted()) {
for($i = 1;$i <= $form['count']->getValue() + 1 ; $i++){
$form->addText('age'.$i, 'Věk osoby č. '.($i + 1));
}
//$form->addText('age'.$i, 'Věk');
} else {
$form->addSelect('count', 'Počet dalších osob', range(1,10) )->addRule(\Nette\Application\UI\Form::FILLED, 'Zvolte pocet...');
$form->addSubmit('show', 'Zobrazit další pole')->setValidationScope(FALSE) ;
}
Takhle mi to funguje tak jak chci. Jen bych se ještě zeptat, jak to zajaxovatět? Aby se to načetlo po změně toho selectboxu, abych na to nemusel klikat „Zobrazit další pole“.
díky moc
- Ot@s
- Backer | 476
colek napsal(a):
Takhle mi to funguje tak jak chci. Jen bych se ještě zeptat, jak to zajaxovatět? Aby se to načetlo po změně toho selectboxu, abych na to nemusel klikat „Zobrazit další pole“.
Asi bys musel formulář manuálně rozepsat v šabloně. Část, ketrou cheš „ajaxovat“ dát do snippetu, na ovládací formulářový prvek navěsit onchange/onblure a pomocí JS submitnout formulář (nebo v tom samém JS nasimuluješ signál s parametrem počtu vypisovaných formuklářovýchy polí).
- colek
- Člen | 59
díky za nakopnutí. Pustil jsem se do toho s vervou ale ani po dnu
zkoušení jsem to nerozchodil… Udělal jsem různí varianty téhož: (osekal
jsem to o ten cyklus, mělo by to přidávat jeden prvek, snad pochopíte co
mám v plánu :) )
V šabloně mám
<tr>
<th>{label count /}</th>
<td>{input count}</td>
</tr>
{snippet formular}
{if isset($potvrzeni)}
<tr>
<th>text</th>
<td>{input age_1}</td>
</tr>
{/if}
{/snippet}
a presenter:
$form->addSelect('count', 'Pocet', range(1,10) )->addRule(\Nette\Application\UI\Form::FILLED, 'Zvolte pocet...')
->getControlPrototype()->onChange("submit()");
$form->addText('age_0', 'Věk osoby č. 1');
if ($form->isSubmitted()) {
$this->invalidateControl('formular');
$this->template->potvrzeni = true;
$form->addText('age_1', 'Věk osoby č. XXX');
}
Pokusil jsem se udělat to co mi napsal Ot@s, ale evidentně jsem někde pochybil.
díky za radu
- Ot@s
- Backer | 476
colek napsal(a):
Pokusil jsem se udělat to co mi napsal Ot@s, ale evidentně jsem někde pochybil.
díky za radu
- Připomínám, že budeš potřebovat ajaxové formuláře a JQuery
- Obsah komponenty v presenteru, resp. formulář
protected function createComponentUkazkovyFormular($name)
$form = new Form($this, $name);
$form->addSelect('count', 'Pocet', range(1,10) )->addRule(\Nette\Application\UI\Form::FILLED, 'Zvolte pocet...');
$age = $form->addContainer('age');
$age->addText('0', 'Věk osoby č. 1');
if ($form->isSubmitted()) {
if ($this->presenter->isAjax()) $this->invalidateControl('formular');
for ($i=1;$i<=$form['count']->getValue();$i++) $age->addText($i, 'Věk osoby č. '.($i+1));
}
$form->addSubmit('show', 'Generovat'); // nahrada za ->getControlPrototype()->onChange() u selectboxu
$form->addSubmit('save', 'Ulozit'); // chybi doplnit onClick s callbackem
return $form;
}
V render příslušného presenteru ještě „namontuj“ formulář do šablony.
$this->template->form = $this['ukazkovyFormular'];
- Šablona
{$form->render('begin')}
<p>
{$form['count']->label}
{$form['count']->control}
{$form['show']->control}
</p>
{snippet formular, table}
<tr n:foreach="$form['age']->getComponents() as $f">
<th>{$f->label}</th><td>{$f->control}</td>
</tr>
{/snippet}
{$form['save']->control}
{$form->render('end')}
<script>
$(function () {
// "naroubovani" ajaxu na formular
$("form").submit(function () {
$(this).ajaxSubmit();
return false;
});
});
</script>
Editoval Ot@s (14. 10. 2011 9:28)
- colek
- Člen | 59
Tak až zas někdy dorazím na PS, máš u mě minimálně pivo :)
Nicméně to „skoro funguje“, ale nepodařilo se mi rozchodit, aby se formulář odeslal po změně u selectboxu. Po stisknutí tlačítka generovat vše funguje.
Js jsem navěsil tak, jak se formulář jmenuje v šabloně, to je asi správný postup ne?
Jenže když udělám selectbox s ->getControlPrototype()->onChange(„submit();“) stejně se to neodešle…
$("frm-travelIForm1").submit(function () {
$(this).ajaxSubmit();
return false;
});
- Ot@s
- Backer | 476
colek napsal(a):
Tak až zas někdy dorazím na PS, máš u mě minimálně pivo :)
Já takto Hosiplanovi dlužím už 3 pivka :-D
Nicméně to „skoro funguje“, ale nepodařilo se mi rozchodit, aby se formulář odeslal po změně u selectboxu. Po stisknutí tlačítka generovat vše funguje.
Doplň si tedy:
<script>
$(function () {
$("#{!$form['count']->getHtmlId()}").change(function(){
$(this).closest('form').submit();
});
$("form").submit(function () {
$(this).ajaxSubmit();
return false;
});
});
</script>
Edit: teoreticky by mělo fungovat i
$form['count']->getControlPrototype()->onChange("$(this).closest('form').submit()")
Editoval Ot@s (14. 10. 2011 14:44)
- colek
- Člen | 59
já nevím, je hodně troufalé tě poprosit se na to podívat? osekal jsem to o vše ostatní a nahrál ke stažení…
já to prostě zkouším, vůbec netuším co dělám špatně…
díky moc
- Ot@s
- Backer | 476
2 věci (viz. opravy v http://www.ulozto.cz/…/example-tgz dostupný do 2011–10–24):
- nenalinkoval jsi do @layout.latte JS knihovny:
- V default.latte, resp. v inline zápisu JS
$("frm-mainIForm1").submit(...);
má být$("#frm-mainIForm1").submit(...);
(chybí #, který říká, že se má hledat v ID tagů). Ještě lepší je ale použít$("#{!$form->getElementPrototype()->id}").submit(...);
(Nette samo dosadí ID formuláře).
PS: Tento přispěvek je přínosný jen pro Tebe ale je neužitečný pro ostatní. Takže buď pošli soukromý vzkaz, nebo uveď indicie tak, aby to bylo užitečné i pro ostatní.
- colek
- Člen | 59
Díky moc! Ještě asi drobnost…
jak nastavit, aby se formulář nevalidoval? Protože musím nejdříve vyplnit celý form, než budu měnit počet políček.
<script>
$(function () {
$("#{!$form['count']->getHtmlId()}").change(function(){
$(this).closest('form').submit();
});
$("#{!$form['count']->getHtmlId()}").submit(function () {
$(this).ajaxSubmit();
return false;
});
});
</script>
- Ot@s
- Backer | 476
colek napsal(a):
jak nastavit, aby se formulář nevalidoval? Protože musím nejdříve vyplnit celý form, než budu měnit počet políček.
Zkus trik, kterým spojíš příjemné s užitečným:
- ponech v definici formuláře submitovací tl. (pomocí setValidationScope zakážeš validaci)
$form->addSubmit('show', 'Generovat')->setValidationScope(FALSE); // do sablony pak pridej {$form['show']->control}
- pomocí JS
$("#{!$form['show']->getHtmlId()}").hide();
ho zneviditelni (když někdo zakáže v prohlížeči JS, bude formulář funkční) - Pomoci JQuery nesubmituj formulář, ale simuluj klik na submitovaci tl., které má vyplou validaci:
$(function () {
$("#{!$form['show']->getHtmlId()}").hide();
$("#{!$form['count']->getHtmlId()}").change(function(){
// $(this).closest('form').submit(); // nesubmitujeme formular
$("#{!$form['show']->getHtmlId()}").click(); // ale simulujeme click na submitbutton
});
// aktivace ajaxoveho submitnuti
$("form").submit(function () {
$(this).ajaxSubmit();
return false;
});
});