Checkbox v poli

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

Ahoj,

Mám takový problém, už to hledám fakt dlouho a nedaří se mi …

Jak udělat checkbox tak aby se mi po odeslání formuláře přes cyklus vložili zaškrtnutá políčka do DB…

Dejme tomu že mám tabulky
group(id,name)
event(id,description)
group_has_event(group_id,event_id)

A já se tady snažím udělat to aby se vylistovali do formuláře všechny groupy uživatele s checkboxem a po zaškrtání některých z nich se ty co byli zaškrtnutý vložili do group_has_event. Aby v event_id bylo id eventu (to pořešim přes URL) a v group_id id té zaškrtnuté grupy. Jak to mám prosím poskládat dohromady???

PS.: Kdyby se přidala ještě jedna tabulka např. subgroup(id,group_id,parent_id…) a fungovalo by to jako stromová struktura, jak by se to udělalo aby byl ve formuláři výpis nějak takto:

GROUP A
checkbox – subgroup A-A
checkbox – subgroup A-B
checkbox – subgroup A-C

GROUP B
checkbox – subgroup B-A
checkbox – subgroup B-B
checkbox – subgroup B-C

a fungovalo by to stejně, čili že zaškrtám a odešlu tlačítkem a do group_has_event by se zase vložili jenom subgroup_id a event_id…

Díky moc

Panda
Člen | 569
+
0
-

Nějak pořádně nechápu ten příklad s databází (pravděpodobně to bude únavou), takže Ti zkusím odpovědět a budu doufat, že Ti to alespoň trochu pomůže.

Při sestavování formuláře použij toto:

<?php
	$items = dibi::query('SELECT * FROM `group` WHERE ...');
	// Do formuláře přidáme 'jmenný kontejner', do kterého umístíme checkboxy
	$containter = $form->addContainer('selected');
	foreach ($items as $item) {
		// Checkboxy budou mít atribut name nastaven na selected[$id],
		// s hodnotami tedy půjde pracovat jako s polem
		$container->addCheckbox((string) $item->id, $item->name);
	}
?>

A jeho zpracování:

<?php
	$values = $form->getValues();

	// ...

	// Projdeme jmenný kontejner selected s checboxy
	foreach ($values['selected'] as $id => $value) {
		// Vybrané checkboxy mají hodnotu nastavenou na TRUE, jejich klíč
		// v poli je ID skupiny
		if ($value) {
			dibi::query('INSERT INTO `group_has_event` VALUES(%i, %i)', $id, $event_id);
		}
	}

	// ...
?>

Za chvilku to zkusím ještě nějak okomentovat…
// Doplnění: pokus dokončen.

Editoval Panda (1. 6. 2009 18:38)

okrajek
Člen | 5
+
0
-

Milý Pando, děkuji mnohokráte … hnedle ozkouším, jestli to bude fungovat a vypadá to jako že bude tak jsi mi velmi pomohl a ostatním možná taky :)

tondovo
Člen | 10
+
0
-

Ahoj,
chtěl bych se zeptat, když tímto způsobem vytvořím skupinu checkboxů, jak nastavím pravidlo, aby byl alespoň jeden zatržen?

Díky

vlki
Člen | 218
+
0
-

Bojím se, že by to muselo být řešeno složitějším definováním konstrukcemi addConditionOn, kde by se vytvořil nějaký kontrolní prvek (šlo by použít třeba i první checkbox) a tomu nastavit, aby vykazoval nevaliditu, když je vše nezatrhnuté…

Pokud bych to měl předvést na příkladu výše uvedeném, tak něco v tomto stylu… Píšu z hlavy:

<?php
        $items = dibi::query('SELECT * FROM `group` WHERE ...')->fetchAll();
        // Do formuláře přidáme 'jmenný kontejner', do kterého umístíme checkboxy
        $containter = $form->addContainer('selected');
	// potřebujeme aspoň jeden checkbox, který bude ten kontrolní
	if (count($items) > 0) {
		$firstItem = array_shift($items);
		$fluentRule = $container->addCheckbox((string) $firstItem->id, $firstItem->name);
        	foreach ($items as $item) {
                	// Checkboxy budou mít atribut name nastaven na selected[$id],
                	// s hodnotami tedy půjde pracovat jako s polem
                	$formItem = $container->addCheckbox((string) $item->id, $item->name);

			// řetězení podmínek - je checkbox nezatrhnutý?
			$fluentRule->addConditionOn($formItem, Form::EQUAL, FALSE);
        	}
		// pokud jsou všechny podmínky definované v cyklu splněné, dojde to až sem,
		//  kde se zkontroluje, jestli je zatrhnutý ten první. Pokud ano, validace
		//  projde. Pokud ne, hodí to hlášku...
		$fluentRule->addRule(Form::FILLED, 'Musíte něco zatrhnout...!');
	}
?>

Druhou možností je využítí CheckboxListu . U něho si ale nejsem jistý čistotou návrhu. Také u něj nefunguje JS validace, která by u výše nastíněného řešení měla fungovat.

Editoval vlki (16. 6. 2009 18:54)

tondovo
Člen | 10
+
0
-

Tohle nemůže fungovat, protože $items není pole, nějak to celý moc nechápu.
Nevedla by cesta přes vlastní validační pravidlo?

<?php
function myValidator($item){
...
}
$container->addCheckbox((string) $item->id, $item->name)
 ->addRule('myValidator', '');
?>

Něco jsem zkoušel, ale bez úspěchu

vlki
Člen | 218
+
0
-

Řešit to vlastním validátorem pro jeden prvek mi to přijde jako silné lámání přes koleno.

V nastíněném řešení nešlo až tak o to okolí, ale přímo o to řetězení podmínek. Samozřejmě, že $items nebude pole, protože dibi::query vrací DibiResult. Pole prvků se z toho vytvoří metodou fetchAll, takže jsem svůj předchozí příspěvek opravil a snad by to už i reálně fungovalo.

Šaman
Člen | 2635
+
0
-

vlki: Tak jsem to zkoušel použít a nakonec se mi to podařilo rozchodit. Ale s jednou opravou – addConditionOn vrací novou větev validačních pravidel, ale nenastaví jí jako aktivní. Takže se sice přidá nová podmínka, ale další se s ní neřetězí, nýbrž se vyhodnotí nezávisle. Proto se jediné validační pravidlo projevilo vždy, i pokud byly některé checkboxy zatržené.

Takže finální verze vypadá takhle:

<?php
$items = dibi::query('SELECT * FROM `group` WHERE ...')->fetchAll();
// Do formuláře přidáme 'jmenný kontejner', do kterého umístíme checkboxy
$containter = $form->addContainer('selected');
// potřebujeme aspoň jeden checkbox, který bude ten kontrolní
if (count($items) > 0) {
    $firstItem = array_shift($items);
    $fluentRule = $container->addCheckbox((string) $firstItem->id, $firstItem->name);
    foreach ($items as $item) {
        // Checkboxy budou mít atribut name nastaven na selected[$id],
        // s hodnotami tedy půjde pracovat jako s polem
        $formItem = $container->addCheckbox((string) $item->id, $item->name);

        // řetězení podmínek - je checkbox nezatrhnutý?
        // TADY JE TEN ROZDÍL
        $fluentRule = $fluentRule->addConditionOn($formItem, Form::EQUAL, FALSE);
    }
    // pokud jsou všechny podmínky definované v cyklu splněné, dojde to až sem,
    //  kde se zkontroluje, jestli je zatrhnutý ten první. Pokud ano, validace
    //  projde. Pokud ne, hodí to hlášku...
    $fluentRule->addRule(Form::FILLED, 'Musíte něco zatrhnout...!');
}
?>