Více skupin vnořených do jedné skupiny

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Blizzy
Člen | 149
+
0
-

Jak pomocí Nette/Forms udělat následující:

SKUPINA 1
	INPUTY

	SKUPINA 2
		INPUTY

	SKUPINA 3
		INPUTY

Vytvořím si skupinu 1, ale mohu jí dát pouze nastavení embedNext, díky kterému bude skupina 2 uvnitř skupiny 1. Jak do skupiny 1 vložit i skupinu 3?

syntax
Člen | 1
+
0
-

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?

Blizzy
Člen | 149
+
0
-

Co kdyby option embedNext nebylo typu boolean, ale číselné? Nebylo by to lepší?

norbe
Backer | 405
+
0
-

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)

xuffo
Člen | 2
+
0
-

Přimlouvám se za replace kódu v distribuci podle výše uvedeného příspěvku od norbe – kód mám vyzkoušený, funguje jak má a myslím, že by se to spoustě programátorů v Nette hodilo.

smarek
Člen | 9
+
0
-

Pánové, tohle je ale nápad ! ;)

Vážně se přimlouvám za tuto změnu ve Frameworku. Přesně to co jsem potřeboval :)

Díky norbe
Díky předem Davide

Honza Kuchař
Člen | 1662
+
0
-

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

Blizzy
Člen | 149
+
0
-

Norbovo řešení vypadá velmi dobře, sám bych na to asi neměl. Dokud se to neobjeví v distribuci, budu ho používat.

blacksun
Člen | 177
+
0
-

Velice děkuji za norbovo řešení!

Dnes jsem na tento problém narazil a tento upravený kód mi velice pomohl a zkrátil čas řešení.

Jsem též pro přidání do distribuce, funguje ok.

norbe
Backer | 405
+
0
-

Mám takový pocit, že do distribuce už se to asi nedostane, jelikož David se snaží ConventionalRenderer-u zbavit (měl by jít poměrně efektně nahradit šablonou).

blacksun
Člen | 177
+
0
-

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
+
0
-

Ú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).

blacksun
Člen | 177
+
0
-

Jasně, nemyslel jsem to jako nedostatek tvého řešení, spíš obecně.. Pak jsem na to už přišel.. ;)

Endrju
Člen | 147
+
0
-

zrovna neco takoveho hledam :)! ale koukam, ze to v distribuci neni.. :/. Je to stale kompatibilni s aktualni verzi nette 0.9.4-PHP5.2 ?

norbe
Backer | 405
+
0
-

Nezkoušel jsem to, ale předpokládám že by neměl být problém (v ConventialRenderu se toho už moc nemění, kvůli plánovanému přechodu na šablony…).

22
Člen | 1478
+
0
-

Potřeboval bych udělat jen prázdnou grupu okolo vnořených group, jde nějak vykreslit prázdnou skupinu?

Editoval 22 (13. 9. 2010 12:23)

Petr Mašát
Člen | 101
+
0
-

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
+
0
-

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)

romiix.org
Člen | 343
+
0
-

Martin napsal(a):

Vďaka, práve som to potreboval – využil ;)