Manuální vytváření formulářů – co se submit?
- Fera
- Člen | 22
Zdravím,
rád bych poprosil o radu ohledně ručního vytváření formulářů. Dělám
„file managera“ kdy skript v presenteru prochází složky a soubory
ukládá do pole. Toto pole jsem chtěl v šabloně vykreslit společně
s checkboxy a jedním submitem abych mohl tyto soubory mazat. Jelikož nevím
dopředu kolik souborů bude, vyhnul jsem se komponentě a snažím se přijít
na to, jak formulář vykreslit ručně.
(vykreslení souborů s checkboxy mám, i submit/button) ale nevím jak jej
svázat z5 s presenterem. Potřeboval bych něco jako setAction na tlačítko,
ale vážně nevím jak. Pokud je můj postup uplně zle, tak mě prosím někdo
naveďte, nejvíc užitečná mi ovšem bude přímo nějaká
ukázka kódu.
tady je úsek kódu pro nastínění oč se snažím.
<form>
<div id="list">
{foreach $files as $file}
<div>
<div>
<img src="{$basePath}/images/jpgFileList.png">
</div>
<div>
<input type=checkbox name="jpgfile" value="{$file}">
</div>
</div>
{/foreach}
</div>
<input type="button" name="Delete" value="Delete" action="hello">
</form>
- David Matějka
- Moderator | 6445
- Vytvor si normalne v presenteru formular s tlacitkem
- s temi checkboxy mas dve moznost
a. vytvoris si v tom presenteru ve formulari X checkboxu (preci ty soubory znas)
b. nebo pouzij low level formulare
- h4kuna
- Backer | 740
taky ti nebude fungovat
<input type=checkbox name="jpgfile" value="{$file}">
Název musí být unikátní.
Udělal bych si službu která bude řešit hledání na filesystému a pak ti ty soubory vrátí v poli a to pole znovu projdeš pro sestavení formuláře. Pokud se chceš vyhnout dvojitému průchodu tak si službě předej callback co bude vytvářet checkboxy a pak spusť prohledávání. Nevidím problém v komponentě. Checkboxy si vytvoř do Containeru až je budeš procházet při vykreslování, aby se ti tam nepletl submit a jiné nežádoucí prvky, které si vykreslíš ručně nad/pod iterací.
Editoval h4kuna (24. 6. 2015 12:32)
- Fera
- Člen | 22
Ok, tak jsem zase v koncích. Momentálně mám takový problém, že se všechno hezky vykreslí, ale tlačítko nereaguje na signály – pokud to mam takto, tak respektive se metoda Succeeded provede hned po nacteni stranky a kdyz odkomentuju callbacka a zakomentuju radek nad nim, tak se zase signal neprovede nikdy ale k obnoveni/odeslani stranky dojde. Prosim o radu
v presenteru mám:
protected function createComponentDeletejpgForm($howMany){
// Definition of formular for next usage
$form = new \Nette\Application\UI\Form;
for ($i = 1; $i <= $howMany; $i++){
$form->addCheckbox('jpgFileChckbx'.$i, null);
}
$form->setMethod('POST');
$form->addCheckbox('selectAll', NULL);
$form->addSubmit('delete', 'Delete');
$form['delete']->getControlPrototype()->class('jpgDelete');
$form->onSuccess[] = $this->deletejpgFormSucceeded($form);
//$form->onSuccess[] = callback('this', 'deletejpgFormSucceeded');
return $form;
}
protected function deletejpgFormSucceeded($form){
// Definition of formular for next usage
//dump('hey');
echo "string";
//$this->redirect('Homepage:');
}
v metodě render mám následující:
$this->template->listForm = $this->createComponentDeletejpgForm(count($files));
a v šabloně:
<form>
<div id="list">
<?php $i = 0; ?>
{foreach $files as $file}
<?php $i++; ?>
{if $iterator->odd}
<div class="oneFileInList listOdd">
{else}
<div class="oneFileInList">
{/if}
<div class="jpgimage">
<img src="{$basePath}/images/jpgFileList.png">
</div>
<div class="jpgname">
<a n:href="downloadfile!, $file, $workingSlot">{$file}</a>
</div>
<div class="chckbx">
{$listForm['jpgFileChckbx'.$i]->control}
</div>
</div>
<div style="clear:both"></div>
{/foreach}
</div>
<div>
<div class="deleteDiv">
{$listForm['delete']->control}
</div>
<div class="selectAllDiv">
{label $listForm['selectAll']}Select all{/label}
{$listForm['selectAll']->control}
</div>
</div>
<div style="clear:both"></div>
</form>
- h4kuna
- Backer | 740
Protože to nesmí být protected ale public
<?php
public function deletejpgFormSucceeded...
?>
Mimochodem máš tam celkem dost postupů, které by šli dělat lépe.
- container namísto postfixu
<?php
for ($i = 1; $i <= $howMany; $i++){
$form->addCheckbox('jpgFileChckbx'.$i, null);
}
?>
Doporučuji:
<?php
$files = $form->addContainer('jpgFileChckbx');
for ($i = 1; $i <= $howMany; $i++){
$files->addCheckbox($i);
}
?>
pak to vykreslíš
{foreach $form['jpgFileChckbx']->getComponents() as $checkbox}
... a zmizí ti $i ta už nebude potřeba
{/foreach}
- toto je správně až opravíš public: $form->onSuccess[] = callback($this, ‚deletejpgFormSucceeded‘);
- $form->setMethod(‚POST‘); to tam být nemusí, POST je default
- tohle budeš muset mít v action jinak to bude zlobit po odeslání formu. $this->createComponentDeletejpgForm(count($files)); ten count bych právě dal do nějaké služby viz post předtím
K šabloně:
- <form> proč? když už máš komponentu?
- zapisuj do šablon pouze párové tagy
viz:
{if $iterator->odd}
<div class="oneFileInList listOdd">
{else}
<div class="oneFileInList">
{/if}
</div>
Doporučuji:
<div class="oneFileInList {if $iterator->odd}listOdd{/if}">
</div>
Editoval h4kuna (25. 6. 2015 12:52)
- Fera
- Člen | 22
Super, děkuju za hezký tutoriál :) Nuže dostal jsem se až po bod.
- tohle budeš muset mít v action jinak to bude zlobit po odeslání formu. $this->createComponentDeletejpgForm(count($files)); ten count bych právě dal do nějaké služby viz post předtím
tomuto nějak nerozmím, mohl bys prosím uvést nějaký jednoduchý příklad?…jinak…momentálně se formulář odešle ale pořád to není spojené s tím signálem = tag <form> ma prazdny atribut action…
- h4kuna
- Backer | 740
Kde máš logiku na získání seznamu souborů? Typuji v presenteru, tak ji vyčleň do extra třídy, zaregistruj přes neon a injektni si ji do presenteru. Tím v metodě createComponentDeletejpgForm odstraň první parametr a naplň si ho v těle metody pomocí vlastnosti presenteru, která bude mít instanci té nové injektnuté třídy.
Pak ukaž jak máš šablonu a presenter.
- Fera
- Člen | 22
Ok, takže jestli to chápu správně, ty máš pocit, že to nefunguje dobře, protože tam cpu ten parametr při vytváření formu, zkusil jsem tedy udělat metodu createComponentDeletejpgForm() bez argumentu. tady je kód:
protected function createComponentDeletejpgForm(){
// Definition of formular for next usage
$form = new \Nette\Application\UI\Form;
for ($i = 1; $i <= 4; $i++){
$form->addCheckbox('jpgFileChckbx'.$i, null);
}
$form->setMethod('POST');
$form->addCheckbox('selectAll', NULL);
$form->addSubmit('delete', 'Delete');
$form['delete']->getControlPrototype()->class('jpgDelete');
//$form->onSuccess[] = $this->deletejpgFormSucceeded($form);
$form->onSuccess[] = callback($this, 'deletejpgFormSucceeded');
return $form;
}
public function deletejpgFormSucceeded($form){
// Definition of formular for next usage
//dump('hey');
echo "string";
//$this->redirect('Homepage:');
}
$this->template->listForm = $this->createComponentDeletejpgForm();
a stale to nefunguje.
- David Matějka
- Moderator | 6445
Projdi si quickstart a precti si dokumentaci formularu, tam je to popsane.
- Fera
- Člen | 22
Tady je šablona:
v te jsem zmeny zatim nedelal.
<?php $listForm->render('begin') ?>
<?php $listForm->render('error') ?>
<div id="list">
<?php $i = 0; ?>
{foreach $files as $file}
<?php $i++; ?>
{if $iterator->odd}
<div class="oneFileInList listOdd">
{else}
<div class="oneFileInList">
{/if}
<div class="jpgimage">
<img src="{$basePath}/images/jpgFileList.png">
</div>
<div class="jpgname">
<a n:href="downloadfile!, $file, $workingSlot">{$file}</a>
</div>
<div class="chckbx">
{$listForm['jpgFileChckbx'.$i]->control}
</div>
</div>
<div style="clear:both"></div>
{/foreach}
</div>
<div>
<div class="deleteDiv">
{$listForm['delete']->control}
</div>
<div class="selectAllDiv">
{label $listForm['selectAll']}Select all{/label}
{$listForm['selectAll']->control}
</div>
</div>
<div style="clear:both"></div>
<?php $listForm->render('end') ?>
zkusil jsem vykreslit i ten formular celej pomoci {control $listForm}, formular se vykreslil i s tlacitkem, a to tlacitko ma stejnou odezvu jako to manualne vykreslene…
- David Matějka
- Moderator | 6445
tu metodu createComponentDeletejpgForm
nemas volat rucne. Precti
si, prosim, dokumentaci..
- Fera
- Člen | 22
Tak jsem to konečně nějak sprovoznil, kdyby v budoucnu měl někdo jiný podobnou otázku, tady je můj kód…určitě by to šlo i líp :).
v presenteru:
protected function createComponentDeletejpgForm(){
.
.
.
$form = new \Nette\Application\UI\Form;
$chckboxs = $form->addContainer('jpgFileChckbx');
for ($i = 1; $i <= count($files); $i++){
$chckboxs->addCheckbox($i);
}
$form->addCheckbox('selectAll', NULL);
$form->addSubmit('delete', 'Delete');
$form['delete']->getControlPrototype()->class('jpgDelete');
$form->onSuccess[] = callback($this, 'deletejpgFormSucceeded');
return $form;
}
presenter render:
.
.
.
// indexace zacina od 2 => $files[0], $files[1]' == undefined offset
$files = array_diff(scandir($path), array('..','.'));
$this->template->files = $files;
.
.
.
v sablone:
{form deletejpgForm}
<div id="list">
<?php $i = 2; ?>
{foreach $form['jpgFileChckbx']->getComponents() as $control}
<div class="oneFileInList {if $iterator->odd}listOdd{/if}">
<div class="jpgimage">
<img src="{$basePath}/images/jpgFileList.png">
</div>
<div class="jpgname">
<a n:href="downloadfile!, $files[$i], $workingSlot">{$files[$i]}</a>
</div>
<div class="chckbx">
{input $control}
</div>
</div>
<div style="clear:both"></div>
<?php $i++; ?>
{/foreach}
</div>
<div>
<div class="deleteDiv">
{input delete}
</div>
<div class="selectAllDiv">
{label selectAll}Select all{/label}
{input selectAll}
</div>
</div>
<div style="clear:both"></div>
{/form}
Editoval Fera (26. 6. 2015 11:23)