Více skupin vnořených do jedné skupiny
- syntax
- Člen | 1
Mám stejný problém.
Skupiny je možné pouze jednou vnořit; pokud bych vložil SKUPINU 2 a pak
nastavil přes setCurrentGroup SKUPINU 1, bude SKUPINA 3 na stejné úrovni
jako SKUPINA 1. Případně pokud bych se pokusil přidávat další prvky
přímo do SKUPINY 1, budou pohromadě s INPUTY a SKUPINA 2 bude následovat
až potom.
Teoreticky by se to dalo obejít přes Nette\Web\Html ale netuším jak. Poradí někdo?
- norbe
- Backer | 405
Taky bych se chtěl přimluvit za přidání této úpravy, dokonce jsem si
pohrál se zdrojákem a už to funguje, takže stačí jen Copy & Paste
(nejlépe do distribuce, funkčnost je 100% kompatibilní) :-)
Tady je ona úprava (soubor
„libs/Nette/Forms/Renderers/ConventionalRenderer.php“):
/**
* Renders form body.
* @return string
*/
public function renderBody()
{
$s = '';
$opened = 0;
$opened_before = $remains = array();
$defaultContainer = $this->getWrapper('group container');
$translator = $this->form->getTranslator();
foreach ($this->form->getGroups() as $group) {
if (!$group->getControls() || !$group->getOption('visual')) continue;
$container = $group->getOption('container', $defaultContainer);
$container = $container instanceof Html ? clone $container : Html::el($container);
$s .= "\n" . $container->startTag();
$text = $group->getOption('label');
if ($text instanceof Html) {
$s .= $text;
} elseif (is_string($text)) {
if ($translator !== NULL) {
$text = $translator->translate($text);
}
$s .= "\n" . $this->getWrapper('group label')->setText($text) . "\n";
}
$text = $group->getOption('description');
if ($text instanceof Html) {
$s .= $text;
} elseif (is_string($text)) {
if ($translator !== NULL) {
$text = $translator->translate($text);
}
$s .= $this->getWrapper('group description')->setText($text) . "\n";
}
$s .= $this->renderControls($group);
$opened = (int)$group->getOption('embedNext');
if ($opened > 0) {
array_push($opened_before, --$opened);
array_push($remains, $container->endTag());
} else {
$s .= $container->endTag() . "\n";
while(count($opened)) {
$opened = array_pop($opened_before);
if($opened) {
array_push($opened_before, --$opened);
break;
} else
$s .= array_pop($remains) . "\n";
}
}
}
while(count($remains)) $s .= array_pop($remains)."\n";
$s .= $this->renderControls($this->form);
$container = $this->getWrapper('form container');
$container->setHtml($s);
return $container->render(0);
}
Testoval jsem to na následujícím formuláři, tak by to snad mělo být 100% funkční…
Group A , embedNext 2
Group B, embedNext 1
Group C, embedNext 3
Group D
Group E
Group F, embedNext 1
Group G
Group H
Group I
protected function createComponentTest($name)
{
$form = new AppForm($this, $name);
$form->addGroup("a2+")
->setOption('embedNext', 2);
$form->addText("inputA");
$form->addGroup("b1+")
->setOption('embedNext', TRUE);
$form->addText("inputB");
$form->addGroup("c3+")
->setOption('embedNext', 3);
$form->addText("inputC");
$form->addGroup("d0");
$form->addText("inputD");
$form->addGroup("e0");
$form->addText("inputE");
$form->addGroup("f1+")
->setOption('embedNext', 1);
$form->addText("inputF");
$form->addGroup("g0");
$form->addText("inputG");
$form->addGroup("h0");
$form->addText("inputH");
$form->addGroup("i0");
$form->addText("inputI");
return $form;
}
Editoval norbe (22. 7. 2009 9:00)
- Honza Kuchař
- Člen | 1662
Jsem taky pro. Tohle je totiž asi nejslabší část formulářů v Nette.
Jenom připomínám, taky jsem nachystal jeden copy&paste kód, ale nikdo nereagoval. :( {Snippet} a jeho druhý parametr
- blacksun
- Člen | 177
Narazil jsem na jednu nefunkčnost norbova řešení, se kterou si nevím nějak efektivně rady..
Formulář se mi celkem zblázní, pokud ve skupině nejsou přímo žádné prvky kromě dvou dalších skupin. Nastavím embedNext na 2, v dalších skupinách již prvky jsou. Skupina se nevykreslí vůbec a jakoby se přeskočí.
Edit: Jak už to tak bývá, hned po odeslání příspěvku mě to
trklo.
Stačí upravit podmínku na začátku cyklu, aby se vykreslovaly i
„zdánlivě“ prázdné skupiny.
<?php
- if (!$group->getControls() || !$group->getOption('visual')) continue;
+ if (!$group->getOption('visual')) continue;
?>
Editoval blacksun (30. 11. 2009 18:49)
- norbe
- Backer | 405
Úplně stejně se chová nepatchnutý Conventional render, takže to není chyba v mém řešení, ale v nette :-) Odstranit by to neměl být problém (viz. kód ConventionalRenderu, která způsobí, že skupiny bez žádného prvku nejsou vůbec vykresleny).
- Petr Mašát
- Člen | 101
Ahoj všichni,
vnořené skupiny jsou super, ale potřeboval bych obdobu toho co tu psal
uživatel „22“.
Mám tento kód
<?php
$form->addGroup('Stávající fotografie')
->setOption('embedNext', true)
->setOption('visual', true);
$form->addGroup()
->setOption('container', \Nette\Web\Html::el('div')->class('tableBox'));
/* ...
nějaké ty vypsané obrázky s checkboxy
... */
$form->addSubmit('deleteButton', 'Smazat označené')
->onClick[] = callback($this, 'edit_delete_click');
?>
Tak se mi první addGroup nevykreslí, protože si myslí že je prázdný.
Nebylo by dobré, když mu zašlu addGroup
s vyloženě řečeným
že chci setOption('visual', true)
tak aby se vykreslila za každé
okolnosti?
Díky moc za reakci,
pm*
- Martin
- Člen | 171
Norbe: Dík, funguje to skvěle. Jen pro ty, kteří nechtějí sahat do kódu Nette a nechce se jim patlat se v těch třídách stejně dlouho jako já (předpokládám, že to brzy bude v dokumentaci, nebo v ní neumím hledat, zatím jsem vycházel jen ze zdrojáků):
<?php
class MyFormRenderer extends Nette\Forms\DefaultFormRenderer implements Nette\Forms\IFormRenderer
{
/**
* Renders form body.
* @return string
*/
public function renderBody()
{
.... viz Norbe ...
}
}
class MyPresenter extends BasePresenter
protected function createComponentTest($name)
{
.... viz Norbe ...
$form->setRenderer(new MyFormRenderer);
return $form;
}
public function renderDefault()
{
...
$ComponentTest = $this['Test']; // získá komponentu
...
}
}
?>
Editoval Martin (26. 2. 2011 2:36)