Checkboxlist
- timbulko
- Člen | 85
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
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
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ě.
- t.prochazka
- Člen | 6
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.
- vlki
- Člen | 218
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
Je škoda aby tahle komponenta zůstala zapadlá ve fóru, nechceš ji vlki přidat do extras?
- vlki
- Člen | 218
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?
- vlki
- Člen | 218
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?
- lucass
- Člen | 89
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
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 :)
- kraklin
- Člen | 12
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
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
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 FormContainer
i 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
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
FormContainer
i aForm
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
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)
- kraklin
- Člen | 12
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
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.
- kravčo
- Člen | 721
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
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.
- m0ufa
- Člen | 2
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.
- Ondřej Mirtes
- Člen | 1536
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é.