[nette:forms] vliv toggle i na data

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Vitek Jezek
hledá kolegy | 285
+
0
-

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? : )

David Grudl
Nette Core | 8218
+
0
-

Co myslíš tím „ze se vezmou“?

pmg
Člen | 372
+
0
-

Chápu to tak, že třeba funkce Form::getValues by nevracela hodnoty polí, které nebyly tooglované.

mavater
Člen | 6
+
0
-

To by moc dobře nešlo. Toggle skrývá celý HTML element s id (což nemusí být ani formulářový prvek, třebas jen nějaký popisek), nikoli jeden formulářový prvek.

_Martin_
Generous Backer | 679
+
0
-

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

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…)“.

smarek
Člen | 9
+
0
-

jak to vypadá s implementací tohodle nápadu?

Honza Kuchař
Člen | 1662
+
0
-

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

myslíte to hotové řešení zde→ https://forum.nette.org/…edne-skupiny ?

smarek
Člen | 9
+
0
-

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');
Honza Kuchař
Člen | 1662
+
0
-

smarek: Ano, až to bude fungovat jako tam. Ale zatím to není v distribuci.

MzK
Člen | 127
+
0
-

Jenom se zeptám, jaká je současná situace?
Jak zajistit, aby se nezobrazená (toggle) skupina neodesílala?
Nějak do appform setDisabled?

Editoval zacatecnik (3. 2. 2010 15:40)

Martin
Člen | 171
+
0
-

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

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

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)