[nette:forms] vliv toggle i na data
- Vitek Jezek
- hledá kolegy | 285
hodilo by se mi, aby „->toggle(‚nejakeID‘)“ melo take vliv na data (tj. kdyz je zaskrtle, tak se data vevnitr vezmou a kdyz neni, tak se nevezmou). Chapu, ze bych pote musel nejak definovat, ktere data patri k danemu ‚toggle‘ (protoze nyni to pouze nastavuje CSS vlastnost /display/), ale mam za to, ze to bude stat za to – logiku bych mel na jednom miste a nemusel bych ji zajistovat z dvou ruznych mist v kodu (do toho se mi opravdu nechce ; ).
Co myslite? : )
- _Martin_
- Generous Backer | 679
David Grudl napsal(a):
Co myslíš tím „ze se vezmou“?
On tím Vítek chtěl suplovat ono
$form->addCheckbox('send', 'Ship to address')
->addCondition(Form::EQUAL, TRUE)
->toggle('sendBox');
$form->addGroup()
->setOption('container', Html::el('div')->id('sendBox'));
$form->addText('city', 'City:', 35)
->addConditionOn($form['send'], Form::EQUAL, TRUE) // <--- tohle
->addRule(Form::FILLED, 'Enter your shipping address');
- Vitek Jezek
- hledá kolegy | 285
David Grudl: tj. ze se odeslou, resp ze budou vraceny v poli $form->getValues (viz nize)
pmg: presne tak!
mavater: ano, to vim, proto by bylo nutne rict, na ktere formularove prvky by se dane toggle aplikovalo (a bylo by velice cool, kdyby si to odsud bral i ConventionalRenderer bez dalsiho nastavovani)
_Martin_: ne tak docela – moje hlavni idea je, ze polozky, ktere nemuzes editovat (tj nemas zaskrtly „togglící“ checkbox) ti nette v poli $form->getValues vrati s hodnotou NULL. Tedy ty pak nemusis mit logiku, kde budes definovat: „pokud nebude zaskrtly checkbox ‚pronajem‘, unsetni pred ulozenim do SQL polozku ‚pronajem-cena‘, ‚datum nastehovani‘ atd…)“.
- Honza Kuchař
- Člen | 1662
Já bych byl taky pro. Ale předpokládám, že se to dostane na řadu až někdy po podpoře podskupin.
- smarek
- Člen | 9
Ale na druhou stranu, tyhle vícenásobný podmínky vypadaj krásně ne? připomínaj mi dobu kdy sem neuměl ani goto ani switch :)
$f->addSelect('nonsymetric_wireless', 'Vyberte tarif:', $nonsymetric_wireless_select)->skipFirst()->addConditionOn($f['wanna_internet'], Form::EQUAL, TRUE)->addConditionOn($f['net_method'], Form::EQUAL, 'wireless')->addConditionOn($f['wireless_type'],Form::EQUAL,'wireless_nonsymetric')->addRule(Form::FILLED,'Vyberte tarif:'.'Nesymetrický bezdrátový internet');
- Martin
- Člen | 171
Ahoj. Tak jsem se chtěl pocvičit v Nette a udělal jsem Ti „rychlé“ řešení. To jsem netušil, že je to piplačka na více než hodinu:
class ToggleForm extends AppForm
{
public function getValues() {
$newValues = parent::getValues();
$controls = $this->getControls();
foreach ($controls as $name => $control)
{
$rules = $control->getRules();
foreach ($rules as $rule)
{
if ($rule->subRules->getToggles() && !($control->value))
{
$toggles = $rule->subRules->getToggles();
foreach ($toggles as $unsetGroup => $toggle)
{
$groups = $this->getGroups();
foreach ($groups as $group)
{
$container = $group->getOption('container');
$attr = $container->attrs['id'];
if ($attr == $unsetGroup)
{
$unsetControls = $group->getControls();
foreach ($unsetControls as $unsetControl)
{
$unsetName = $unsetControl->getName();
unset($newValues[$unsetName]);
}
}
}
}
}
}
}
return $newValues;
}
}
Omlouvám se za „pascalské“ formátování závorek, ale jsem na to zvyklý a u takhle zanořených cyklů je to rozhodně přehlednější. David by to asi udělal na jeden řádek, já jsem holt jel po zdrojácích a zjišťoval, kam se „toggle“ příznak zapisuje. Samozřejmě by bylo možné použít extension a někam si schovávat seznam „toggleovaných“ controlů už při vytváření, ale takhle je to asi o malinko čistší.
Použití třeba takhle:
class HomepagePresenter extends BasePresenter
{
public function createComponentToggleForm($name) {
$form = new ToggleForm($this, $name);
$form->addCheckbox('send', 'Ship to address')
->addCondition(AppForm::EQUAL, TRUE)
->toggle('sendBox');
$form->addGroup()
->setOption('container', Html::el('div')->id('sendBox'));
$form->addText('city', 'City:', 35)
->addConditionOn($form['send'], AppForm::EQUAL, TRUE)
->addRule(AppForm::FILLED, 'Enter your shipping address');
$form->setCurrentGroup(NULL);
$form->addSubmit('save', 'Ulozit');
$form->onSubmit[] = callback($this, 'formSubmitted');
return $form;
}
function formSubmitted($form) {
$values = $form->values;
$this->redirect('default');
}
public function renderDefault() {
$this->template->anyVariable = 'any value';
}
}
Ještě pozor na „drobnůstku“ – values[‚send‘] vrací FALSE při „odtoggleovaném“ checkboxu.
Editoval Martin (27. 4. 2011 0:08)
- Martin
- Člen | 171
A ještě doplnění k tématu:
Nemyslím si, že by toto bylo správné výchozí chování.
Podle mého názoru by bylo lepší chování funkce toggle() ponechat ve
stávající podobě a v případě zájmu zavěst třeba další funkci
toggleData(), která by označovala „toggleované“ skupiny, jejichž
„poddata“ by se v getValues() ignorovala.
- Martin
- Člen | 171
Takže lépe takto:
class ToggleForm extends AppForm
{
public function getToggledValues() {
$newValues = parent::getValues();
$controls = $this->getControls();
foreach ($controls as $name => $control)
{
$rules = $control->getRules();
foreach ($rules as $rule)
{
if ($rule->subRules->getToggles() && !($control->value))
{
$toggles = $rule->subRules->getToggles();
foreach ($toggles as $unsetGroup => $toggle)
{
$groups = $this->getGroups();
foreach ($groups as $group)
{
$container = $group->getOption('container');
$attr = $container->attrs['id'];
if ($attr == $unsetGroup)
{
$unsetControls = $group->getControls();
foreach ($unsetControls as $unsetControl)
{
$unsetName = $unsetControl->getName();
unset($newValues[$unsetName]);
}
}
}
}
}
}
}
return $newValues;
}
}
A pak použít getValues() pro standardní chování a getToggledValues() pro změněné.
Editoval Martin (28. 4. 2011 11:38)