Checkboxlist

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

Zdravím,
je nejaká možnosť ako by sa dal vytvoriť checkboxlist? Čiže niečo podobné ako radiolist, ale namiesto radio by tam boli checkboxy. http://tophry.net/…kboxlist.png

Vďaka.

Patrik Votoček
Člen | 2221
+
0
-

V nette to aktualně není… Ale možná by ti mohlo pomoct toto https://forum.nette.org/…iewtopic.php?… a da se to resit vice zpusoby vlastni renderer pro formulare. Pak to taky muzes vykreslovat sam vice: https://forum.nette.org/…ni-formularu

t.prochazka
Člen | 6
+
0
-

A není nějak možné pod jeden label vložit více formulářových prvků, něco jako:

<?php

$form->addItem('Label:')
 ->addCheckbox('a1','text1');
 ->addCheckbox('a2','text2');

?>

Taky mi není zatím jasné, jak všechny checkboxy předat jako pole, tedy aby to vygenerovalo name=„d[a]“, name=„d[b]“, name=„d[c]“, jakmile dám d[c] jako name, spadne to na chybě.

Jod
Člen | 701
+
0
-

Dá sa to, ale myslím že defaultný renderer to nezvláda. Takže buď si napíšeš svoj, alebo to vypíšeš do šablony ručne.

Do pola cez container

<?php
$c = $form->addContainer('d');
$c->addCheckbox('a', 'text');
$c->addCheckbox('b', 'text');
?>
t.prochazka
Člen | 6
+
0
-

Díky, to řeší to name=„d[a]“, ale jak dostat třeba dva textová pole vedle sebe, když potřebuji třeba rok zadat od do.

Jod
Člen | 701
+
0
-

Daj jedno rok od a druhé rok do. Ak to chceš vedľa seba som ti napísal, že si buď musíš napísať vlastný renderer, alebo ručne do šablony.

vlki
Člen | 218
+
0
-

Ještě k tomu CheckboxListu. Už to bude pár dní, co jsem si udělal obdobu RadioListu. Místo jedné hodnoty nebo NULL, jako to má RadioList, vrací pole hodnot nebo NULL.

Také u toho nefunguje JS validace filled, takže jsem metodu validateFilled u RadioListu přejmenoval na validateServerFilled, ke které se JS validace negeneruje automaticky.

A proč to není poděděné od RadioListu, když to má víc než polovinu metod stejných? Protože se v getControl využívá featury parent::getControl, což nedělá zrovna to, co by bylo potřeba:)

Tak pokud to někdo využije, copy & pastujte dále…

class CheckboxList extends FormControl
{
	/** @var Nette\Web\Html  separator element template */
	protected $separator;

	/** @var Nette\Web\Html  container element template */
	protected $container;

	/** @var array */
	protected $items = array();

	/**
	 * @param  string  label
	 * @param  array   options from which to choose
	 */
	public function __construct($label, array $items = NULL)
	{
		parent::__construct($label);
		$this->control->type = 'checkbox';
		$this->container = /*Nette\Web\*/Html::el();
		$this->separator = /*Nette\Web\*/Html::el('br');
		if ($items !== NULL) $this->setItems($items);
	}



	/**
	 * Returns selected radio value.
	 * @param  bool
	 * @return mixed
	 */
	public function getValue($raw = FALSE)
	{
		return is_array($this->value) ? $this->value : NULL;
	}



	/**
	 * Sets options from which to choose.
	 * @param  array
	 * @return RadioList  provides a fluent interface
	 */
	public function setItems(array $items)
	{
		$this->items = $items;
		return $this;
	}



	/**
	 * Returns options from which to choose.
	 * @return array
	 */
	final public function getItems()
	{
		return $this->items;
	}



	/**
	 * Returns separator HTML element template.
	 * @return Nette\Web\Html
	 */
	final public function getSeparatorPrototype()
	{
		return $this->separator;
	}



	/**
	 * Returns container HTML element template.
	 * @return Nette\Web\Html
	 */
	final public function getContainerPrototype()
	{
		return $this->container;
	}



	/**
	 * Generates control's HTML element.
	 * @param  mixed
	 * @return Nette\Web\Html
	 */
	public function getControl($key = NULL)
	{
		if ($key === NULL) {
			$container = clone $this->container;
			$separator = (string) $this->separator;

		} elseif (!isset($this->items[$key])) {
			return NULL;
		}

		$control = parent::getControl();
		$control->name .= '[]';
		$id = $control->id;
		$counter = -1;
		$values = $this->value === NULL ? NULL : (array) $this->getValue();
		$label = /*Nette\Web\*/Html::el('label');

		foreach ($this->items as $k => $val) {
			$counter++;
			if ($key !== NULL && $key != $k) continue; // intentionally ==

			$control->id = $label->for = $id . '-' . $counter;
			$control->checked = (count($values) > 0) ? in_array($k, $values) : false;
			$control->value = $k;

			if ($val instanceof /*Nette\Web\*/Html) {
				$label->setHtml($val);
			} else {
				$label->setText($this->translate($val));
			}

			if ($key !== NULL) {
				return (string) $control . (string) $label;
			}

			$container->add((string) $control . (string) $label . $separator);
		}

		return $container;
	}



	/**
	 * Generates label's HTML element.
	 * @return void
	 */
	public function getLabel()
	{
		$label = parent::getLabel();
		$label->for = NULL;
		return $label;
	}

	/**
	 * Filled validator: has been any radio button selected?
	 * @param  IFormControl
	 * @return bool
	 */
	public static function validateServerFilled(IFormControl $control)
	{
		return $control->getValue() !== NULL;
	}

}

A příklad použití…

$form['name'] = new CheckboxList('title', $items);
$form['name']->addRule('CheckboxList::validateServerFilled', 'Zatrhněte něco...!');

Mimochodem, nestálo by za to udělat nějakou abstraktní třídu (idea… FormControlList), od které by RadioList a CheckboxList dědily?

A asi jedna na Davida… Proč není CheckboxList zařazen do výchozích prvků? Je to proto, že může vrátit pole a né jen jednu hodnotu?

Editoval vlki (26. 5. 2009 13:43)

romansklenar
Člen | 655
+
0
-

Je škoda aby tahle komponenta zůstala zapadlá ve fóru, nechceš ji vlki přidat do extras?

vlki
Člen | 218
+
0
-

Jojo, během zítřka jí tam hodím.

vlki
Člen | 218
+
0
-

Extras už mají nové děťátko – CheckboxList :)

Lopo
Člen | 277
+
0
-

404 Not Found
The requested URL /files//checkboxlist.zip does not exist.

vlki
Člen | 218
+
0
-

Opraveno

Lopo
Člen | 277
+
0
-

docela ma pobavilo toto v CheckboxList.php :)
* @package Nette\Extras\Captcha

dotTwelve
Člen | 167
+
0
-

Hlasi mi to chybu: Extension method handler ‚CheckboxList::addCheckboxList‘ is not callable. Co s tim?

vlki
Člen | 218
+
0
-

Lopo napsal(a):

docela ma pobavilo toto v CheckboxList.php :)
* @package Nette\Extras\Captcha

Fixed. Použil jsem Captchu jako pajc. Nestydím se za to:)

dotTwelve napsal(a):

Hlasi mi to chybu: Extension method handler ‚CheckboxList::addCheckboxList‘ is not callable. Co s tim?

Vypadá to jako bys neměl v momentě, kdy registruješ extension metodu, k dispozici třídu CheckboxList. Používáš RobotLoader?

dotTwelve
Člen | 167
+
0
-

Pouzivam, viz:

<?php
$loader = new RobotLoader();
$loader->addDirectory(APP_DIR);
$loader->addDirectory(LIBS_DIR);
$loader->register();
?>
vlki
Člen | 218
+
0
-

A Form::extensionMethod('Form::addCheckboxList', array('CheckboxList', 'addCheckboxList')); máš v bootstrapu? To by ti mělo fungovat… CheckboxList.php máš někde v dosahu toho RobotLoaderu?

Funguje ti CheckboxList bez použití extension metody?
Tzn. místo

$form->addCheckboxList('demo', 'Choices', $items);

tohle..

$form['demo'] = new CheckboxList('Choices', $items);

..?

Zkusil jsi vymazat temp?

dotTwelve
Člen | 167
+
0
-

Tak uz to slape, jak hodinky, jsem tele, sice jsem mazal temp, ale ne kompletne. Diky

lucass
Člen | 89
+
0
-

Zdravím,

vyzkoušel jsem Checkboxlist a zdá se mi, že je nutné překrýt metodu FormControl::setValue($value), aby to po načtení formuláře zaškrtalo příslušná pole, viz kód:

<?php
	...

	public function setValue($value)
	{
		$this->value = is_array($value) ? $value : array($value);
	}

	...
?>

Možná to není chybka a dělá se to v tomto případě jinak. Kdyžtak mě opravte, pokud se mýlím a něco jsem přehlédl.

Doplnění: i když je fakt, že si load stejně musím ručně, páč v DibiRow nikdy nebudu sloupec typu array;) Takže asi nesmyslná připomínka…

Editoval lucass (10. 7. 2009 15:13)

kraklin
Člen | 12
+
0
-

Zdravim,

je nejaka moznost, jak pridat podporu CheckboxListu do kontejneru? Pokud mam napriklad

<?php
...
	$skupina = $form->addContainer('vazba');
	$items = $tiskovina->getPapir();
	$skupina->addCheckboxList('papir','Papír',$items);
...
?>

tak mi nette vyhodi logicky chybu Call to undefined method FormContainer::addCheckboxList()., protoze tu metodu proste nezna. Jenom tak pres:

<?php
Form::extensionMethod('FormContainer::addCheckboxList', array('CheckboxList', 'addCheckboxList'));
?>

ji taky pridat nemuzu, protoze metoda CheckboxList::addCheckboxList bere jako prvni argument typ Form a ne FormContainer.

Jde to nejak vykutit bez prepsani CheckboxListu? At nedelam neco zbytecne :)

vlki
Člen | 218
+
0
-

Hm… a nejde to udělat takto?

<?php
$skupina['papir'] = new CheckboxList('Papír', $items);
?>

Už se mi do toho teď nechce drbat, když to bude David dávat do distribuce.

kraklin
Člen | 12
+
0
-

vlki napsal(a):

Hm… a nejde to udělat takto?

<?php
$skupina['papir'] = new CheckboxList('Papír', $items);
?>

Už se mi do toho teď nechce drbat, když to bude David dávat do distribuce.

no, to praveze nejde. Teda slo by to, ale to bych si to cele kompletne rozbil a to se mi zrovna dvakrat nechce. :( No a jestli to bude David davat do distribuce, nebude lepsi, ze to pojede i uvnitr kontejneru?

EDIT: no jak si tak prochazim zdrojaky FormContainer, tak mas pravdu. Asi to cele rozbiju a udelam znovu. Je mi ale naprosto jasne, ze ve chvili, kdy dopisu posledni strednik po kompletnim prekopani vyda David novou verzi, ktera to bude podporovat :D

Editoval kraklin (11. 9. 2009 18:13)

jasir
Člen | 746
+
0
-

A co bys tím rozbil? Vždyť ta addCheckBoxList dělá toto:

<?php
   public static function addCheckboxList(Form $form, $name, $label, array $items = NULL)
   {
      return $form[$name] = new self($label, $items);
   }
?>

Takže to co píše vlki je ekvivalentní, akorát se to přidává ne do formu, ale do containeru…
Nebo mi něco uniká?

kravčo
Člen | 721
+
0
-

vlki napsal(a):

Už se mi do toho teď nechce drbat, když to bude David dávat do distribuce.

Nemal by si práve preto, že to pôjde do distribúcie, takéto bugy opraviť?

Imho stačí zmeniť class-hint, keďže všetky metódy pridávajúce controly sú implementované vo FormContaineri a Form od neho dedí…

public static function addCheckboxList(FormContainer $container, $name, $label, array $items = NULL)
{
    return $container[$name] = new self($label, $items);
}

a samozrejme opraviť registráciu v bootstrape:

FormContainer::extensionMethod('FormContainer::addCheckboxList', 'CheckboxList::addCheckboxList');
kraklin
Člen | 12
+
0
-

kravčo napsal(a):

vlki napsal(a):

Už se mi do toho teď nechce drbat, když to bude David dávat do distribuce.

Nemal by si práve preto, že to pôjde do distribúcie, takéto bugy opraviť?

Imho stačí zmeniť class-hint, keďže všetky metódy pridávajúce controly sú implementované vo FormContaineri a Form od neho dedí…

public static function addCheckboxList(FormContainer $container, $name, $label, array $items = NULL)
{
    return $container[$name] = new self($label, $items);
}

a samozrejme opraviť registráciu v bootstrape:

FormContainer::extensionMethod('FormContainer::addCheckboxList', 'CheckboxList::addCheckboxList');

presne takhle jsem to chtel vyresit, akorat mi hlasil, ze nemuze predeklarovat addCheckboxList. Tak jsem vytvoril novou:

<?php
	public static function addCheckboxListContainer(FormContainer $form, $name, $label, array $items = NULL)
	{
		return $form[$name] = new self($label, $items);
	}
?>

a do bootstrapu pridal:

Form::extensionMethod('FormContainer::addCheckboxList', array('CheckboxList', 'addCheckboxListContainer'));

a slape to jako hodinky. Je to sice prasarna, ale nechtelo se mi nad tim dlouho badat. Mozna v nejake min vytizene chvilce, ale to driv bude soucasti distribuce :)

kraklin
Člen | 12
+
0
-

jasir napsal(a):

Takže to co píše vlki je ekvivalentní, akorát se to přidává ne do formu, ale do containeru…
Nebo mi něco uniká?

jj je to ekvivalentni, ale v soucasne podobe formulare jaky mam mi to prislo zbytecne komplikovane. Kdyz nad tim premyslim ted, slo by to udelat, ale uz jsem si reseni vytvoril :)

EDIT: No asi uz u toho sedim dlouho, takze mi nejak prestava fungovat mozkovna a odmita premyslet. Samozrejme, ze by to tak slo a nic by se tim nemenilo, jenom jsem si to nekde na ceste monitor->oci->mozek zbytecne zkomplikoval a hned radeji zavrhl, nez abych se zamyslel. Radeji uz to dneska vypinam :)

Editoval kraklin (11. 9. 2009 18:42)

kravčo
Člen | 721
+
0
-

kraklin napsal(a):

presne takhle jsem to chtel vyresit, akorat mi hlasil, ze nemuze predeklarovat addCheckboxList. Tak jsem vytvoril novou:

To je dosť zvláštne… Nemáš tam tú metódu dvakrát?

kraklin
Člen | 12
+
0
-

kravčo napsal(a):

kraklin napsal(a):

presne takhle jsem to chtel vyresit, akorat mi hlasil, ze nemuze predeklarovat addCheckboxList. Tak jsem vytvoril novou:

To je dosť zvláštne… Nemáš tam tú metódu dvakrát?

no ani ne. Neni to nahodou tak, ze kdyz mas metodu se stejnym nazvem musi se lisit poctem argumentu a ne jenom jejich typem aby jsi ji mohl pretizit? V Ccku ti staci zmenit typ k pretizeni ale nevim jak se s timhle pere PHP

vlki
Člen | 218
+
0
-

V Ccku ti staci zmenit typ k pretizeni ale nevim jak se s timhle pere PHP

Přesněji až od C++ ;) A myslím, že toto php nepodporuje, ne?

Nemal by si práve preto, že to pôjde do distribúcie, takéto bugy opraviť?

No, zatím jsem měl takovou zkušenost, že to David stejně vždycky udělal nějak rafinovaněji, než někdo navrhoval:) Toto ještě opravím.

Přemýšlel jsem třeba nad doděláním podpory pravidla FILLED na straně klienta a došel k závěru, že to asi stejně teď nemá cenu.

kraklin
Člen | 12
+
0
-

vlki napsal(a):

Přesněji až od C++ ;) A myslím, že toto php nepodporuje, ne?

samozrejme v C++ :)

kravčo
Člen | 721
+
0
-

kraklin napsal(a):

kravčo napsal(a):

To je dosť zvláštne… Nemáš tam tú metódu dvakrát?

no ani ne. Neni to nahodou tak, ze kdyz mas metodu se stejnym nazvem musi se lisit poctem argumentu a ne jenom jejich typem aby jsi ji mohl pretizit? V Ccku ti staci zmenit typ k pretizeni ale nevim jak se s timhle pere PHP

PHP overloading nepodporuje, navyše ti úplne stačí jedna metóda – tá pre FormContainer.

kraklin
Člen | 12
+
0
-

kravčo napsal(a):

kraklin napsal(a):

kravčo napsal(a):

To je dosť zvláštne… Nemáš tam tú metódu dvakrát?

no ani ne. Neni to nahodou tak, ze kdyz mas metodu se stejnym nazvem musi se lisit poctem argumentu a ne jenom jejich typem aby jsi ji mohl pretizit? V Ccku ti staci zmenit typ k pretizeni ale nevim jak se s timhle pere PHP

PHP overloading nepodporuje, navyše ti úplne stačí jedna metóda – tá pre FormContainer.

jj mas pravdu, staci jenom ta jedna.

zakjan
Člen | 9
+
0
-

Pro použití v aktuálním Nette je potřeba ve zdrojáku trochu upravit metodu getLabel:

public function getLabel($caption = NULL)
{
	$label = parent::getLabel($caption);
vlki
Člen | 218
+
0
-

Opraveno.

Vzhledem k zamčené editaci jsem to nahrál na alternativní server.

CheckboxList na vlki.cz

m0ufa
Člen | 2
+
0
-

ahoj,
můžete mne prosím někdo nakopnout jakým způsobem nastavím jednotlivou položku jako checked?

<?php
	protected function createComponentUserForm()
	{

		$form = new AppForm;
			...
		$roles = array('1'=>'admin', '2'=>'editor', '3'=>'viewer', '4'=>'guest');
		$form->addCheckboxList('roles', 'role:',$roles);
			...
	}
?>

Zkoušel jsem :

<?php
	public function actionDetail($username)
	{

		$form = $this['userForm'];
		$this->template->form = $form;
		$form->fireEvents();

		$this['userForm']->setDefaults(array(
		'roles' => '1'));
	}
?>

a nic…
Díky.

lucass
Člen | 89
+
0
-

Zkus

<?php
	...

	$form['roles']->setDefaultValue(array(1,2,3)); // to pole je neasociativni, jdou to hodnoty jednotlivych checkboxu, tj. budou zaskrtnute admin, editor, viewer

	...
?>
m0ufa
Člen | 2
+
0
-

Vau…, funguje to.

Děkuji.

Ondřej Mirtes
Člen | 1536
+
0
-

Ahoj,
v nové verzi s Nette s novou validací formulářů tento doplněk není kompatibilní – při nastavení setRequired se všechny položky označí jako povinné, tudíž musí být všechny zaškrtnuté.

acidcliq
Člen | 4
+
0
-

technicka, jde nejaky zpusobem manipulovat s labely? (nemyslim hlavni)