Vynechání prvku z vykreslování formuláře
- chemikus
- Člen | 49
Ať použiju TRUE a nebo FALSE, tak se mi prvek stále zobrazuje (a to ho volám přímo v komponentě, kde nastavuji formulář) :-/ A ještě taková perlička. Normálně bych ten prvek chtěl nechat vykreslovat (při vkládání záznamu) ale při jeho editace ho nezobrazovat. Proto při editacei záznamu volám funkci
public function editaceAkce() {
$form = $this->getComponent('akce');
$form["save"]->setRenderer(TRUE);
}
Jo a abych byl ještě přesnější, jedná o prvek, ve kterém připojuji fotografie (soubory)
Editoval chemikus (30. 10. 2010 13:41)
- Mikulas Dite
- Člen | 756
Chápu. Problém je tady docela jasný: funkce editaceAkce()
nic
nedělá. Formulář se vždy vezme z createComponentAkce()
.
Nejsnažší (ale ne nejlepší) je vytvořit formulář pro tvorbu
createComponentAkce()
a poté v
createComponentAkceEdit()
vytvořit nový, třeba takhle:
createComponentAkceEdit()
{
$form = $this->getComponent('akce');
$form["save"]->setRendered(FALSE);
return $form;
}
Mimochodem setRenderer
a setRendered
jsou úplně
jiné věci.
Editoval Mikulas Dite (30. 10. 2010 13:45)
- chemikus
- Člen | 49
Hmm… výsledek stále stejný. Tak znovu více popíšu:
protected function createComponentAkce() {
$form = new NAppForm;
$form->addGroup("Informace o akci");
$form->addText("nazev", "Název: ", "45");
$form["nazev"]->setRendered(TRUE);
//$form["nazev"]->setRendered(FALSE);
$form->addSubmit('odeslat', 'Přidat');
$form->onSubmit[] = array($this, 'akceSubmitted');
return $form;
}
Ale stále se mi vykresluje prvek „nazev“. A to ho nechávám ovlivnit nijak další funkcí co se týče editace nebo tak :-)
A nerad bych vytvářel další komponentu pro editaci a rád bych elegantně schoval možnost přidávání fotografie. Ovšem, komponentu bych tam mohl zanechat, ale již to mám vymyšlené zcela jinak.
- Mikulas Dite
- Člen | 756
Tak jednak Form má fluent interface, takže místo
$form->addText("nazev", "Název: ", "45");
$form["nazev"]->setRendered(FALSE);
se píše
$form->addText("nazev", "Název: ", "45")
->setRendered(FALSE);
Každopádně jsem do kouknul do api a rozhodně jsem tam
setRendered
neviděl. Bavíme se o verzi 2?
Schovávat nějaké políčko ve formuláři takhle bych nezařadil mezi best practice. Teoreticky by šlo formulář tvořit takhle:
$form = AppForm;
//...
if ($this->action == 'akce') {
$form->addText(/*...*/);
}
if ($this->action == 'edit') {
}
return $form;
Imho se ale v první řadě snažíš něco obcházet/řešit jinou než Nette cestou.
Edit: a nemíchej prosím české a anglické názvy ; ) hrozně špatně se to potom čte.
Editoval Mikulas Dite (30. 10. 2010 14:32)
- Solution
- Člen | 50
Zdravím,
zkoušel jsem to také, verze 2 pro 5.2 s prefixy.
Projel jsem conventionalrender(třída pro vykreslování formů), našel jsem
v ní toto:
<?php
foreach ($this->form->getGroups() as $group) {
if (!$group->getControls() || !$group->getOption('visual')) continue;
// V metodě renderBody()
?>
tznm., že když nějakému prvku nastavíte setRendered nebo přes setOption
hodnotu visual na true, tak by
se ta komponenta neměla vykreslit, bohužel se tak děje při obouch stavech,
nevím proč.
Že by chyba? Nebo jsem to jen špatně pochopil?
Zkouším to na tomto:
<?php
$ff = new NForm();
$ff->addButton('Ahoj','caac')->setOption('visual',true);
?>
Editoval Padik (30. 10. 2010 14:36)
- Mikulas Dite
- Člen | 756
Padik napsal(a):
// V metodě renderBody()
To se ale vztahuje na $group
, ne na jednotlivé prvky.
Edit:
$form->addGroup()
->setOption('visual', TRUE);
$form->addCheckbox('checkbox');
by checkbox orámovalo, s FALSE
ne.
Editoval Mikulas Dite (30. 10. 2010 14:41)
- Vyki
- Člen | 388
Nevím jestli jsem dobře pochopil co je konkrétním záměrem, ale dalo by se to udělat např takto:
<?php
//vykresluje formulář pro 2 view - 1) view přidat akci
- 2) view editovat akci
//definice komponenty
protected function createComponentNewsform()
{
$form = new AppForm();
$form->addHidden('id');
$form->addText('name', 'Název akce')
->addRule(Form::FILLED, 'Vyplňte prosím název akce');
$form->addSubmit('savenews', 'Uložit a publikovat')
->onClick[] = callback($this, 'newsClicked');
}
//definice view 1)
public function renderDefault()
{
unset($this['newsform']['id']); //zde odstraním hidden field id, vkládám nový záznam, kde id není známo
}
//definice view 2)
public function renderEdit($id)
{
$data = NewsModel::findById($id)
$this['newsform']->setDefaults(array(
'id' => $data['id'],
'name' => $data['name']
));
}
//definice obsluzne metody
public function newsClicked(SubmitButton $button)
{
$data = $button->getForm()->getValues();
if(isset($data['id']))
{
NewsModel::update($data);
} else {
NewsModel::add($data);
}
}
?>
- Mikulas Dite
- Člen | 756
Padik napsal(a):
V tom případě metoda setRendered je špatně, jelikož na group se nevztahuje.
Právě že správně je, vztahuje se jenom na group.
Viki napsal(a):
Takhle bych to radši nedělal, unset
mi tam
nepříde košer.
Řešení jsou:
- nejlepší je mít pro edit vlastní formulář
- edit formulář odvozený od původního
- mít jednu továrničku a měnit jí podle akce
- a pak další, které obchází logiku stávajících Nette formulářů
- Solution
- Člen | 50
Na group se vztahuje:
<?php
$form->addGroup()->setOption('visual',true); //To ale ovlivnuje vykreslení rámce
?>
na group se setRenderer() nedá aplikovat, ten se dá aplikovat na jednotlivé prvky, viz:
David Grudl
>Zavoláním $form[‚save‘]->setRendered(TRUE) je vynecháte z vykreslování $form->render(‚body‘) a pak je můžete vykreslit ručně.
čili:
<?php
$form->addButton('test','test')->setRendered(true); //Prvek se nemá vykreslit samovolně, pokud se používá conventional render
?>
Takže metoda setRendered() neplní svou fci.
Editoval Padik (30. 10. 2010 17:40)
- Vyki
- Člen | 388
Mikulas Dite napsal(a):
Takhle bych to radši nedělal,unset
mi tam nepříde košer.
Zajímal by mě argument proč to není „košer“. Je to operace na úrovni FormContaineru, jednoduše odeberu jednu položku. Vídíš tam snad nějakou bezpečnostní hrozbu, pokud ano, kde?
Řešení jsou:
- nejlepší je mít pro edit vlastní formulář
To mi rozhodně „nejlepší“ nepřijde. Psát kvůli přidání jedné položky do FormContaineru novou továrničku je v celku zbytečné.
Editoval Vyki (30. 10. 2010 21:21)
- Filip Procházka
- Moderator | 4668
AppForm::render() → Form::renderBegin() – automaticky vyresetuje
všechny prvky na rendered FALSE
, proto to jde použít jedině
v templatě
Skrývání komponent formuláře je prasárnička, udělal bych to nějak takhle :)
private function createMyFormBase($name)
{
$form = new AppForm($this, $name);
$form->adddText('...', ...);
// ...
return $form;
}
public function createComponentMyFormNew($name)
{
$form = $this->createMyFormBase($name);
$form->addSubmit('new', 'Uložit');
$form->onSubmit[] = callback($this, 'saveNew');
return $form;
}
public function createComponentMyFormEdit($name)
{
$form = $this->createMyFormBase($name);
$form->addHidden('id', $this->getParam('editId'));
$form->addSubmit('edit', 'Uložit');
$form->onSubmit[] = callback($this, 'saveEdit');
return $form;
}
Editoval HosipLan (1. 11. 2010 8:58)
- westrem
- Člen | 398
Chemikus by mohol aspon uviest aku verziu Nette pouziva.
V pripade 0.9.* musi setOption('rendered', TRUE)
fungovat,
v preklade to znamena, ze mu akoby dopredu nastavis, ze uz bol vyrendrovany a
teda sa ma preskocit (vid API
), (nechapem tak trochu zmetky s nastavovani na false
alebo
true
:-/ )
V pripade 2.0 aspon podla aktualnej API to musi fungovat tak isto. Nove formulare (ktore uz mali byt commitnute ale nie su), riesia rendering uplne odlisne.
Posli prosim teda viac kodu, aj sablonu napriklad, pretoze to jednoducho fungovat musi.
Co sa tyka setOption('visual', TRUE)
– sposobi, ze sa
nevykreslia prvky danej grupy – teda grupa samotna, jednoducho sa preskoci
v iteracii.
Mikulas Dite napsal:
Takhle bych to radši nedělal, unset mi tam nepříde košer.
Praveze to koser uplne je – je to regulerne odstranenie prvky
z formularu, nie je na tom nic zle. To unset
je v tomto pripade
skratka pre removeComponent
kde pri formulare by si musel predavat
na odstranenie samotnu komponentu a nie len nazov, preto unset
ako
the faster way.
nejlepší je mít pro edit vlastní formulář
Suhlasim s Vyki – toto je imho zla varianta, duplicita kodu, kvoli jednej polozke? Fakt ee ..
Najlepsie riesenie je imho mat tovarnicku, ktora vytvori zakladny skeleton – kostru formularu a potom v patricnych akciach doplnat (vynimocne odoberat) prvky podla potreby.
- Mikulas Dite
- Člen | 756
Vyki napsal(a):
Zajímal by mě argument proč to není „košer“. Je to operace na úrovni FormContaineru, jednoduše odeberu jednu položku. Vídíš tam snad nějakou bezpečnostní hrozbu, pokud ano, kde?
Asi ani ne tak bezpečnostní problém, jako spíš teoretický. Je mi bližší něco opatrně tvořit, než to naskládat v továrničce a poté odebírat. Souhlasím s tebou, že unset nad containerem dokonce ani nemůže zapříčinit nějaký problém.
Podmínka v továrničce je lepší, než úprava formuláře v render
(nemluvím o setDefualts
a vzhledu) – všechny komponenty
formuláře jsou tam na jednom místě. Osobně bych nechtěl projíždět
všechny rendery a hledat, proč se zrovna tady něco nevykreslilo.
Každopádně to tvé řešení je plně funkční a správné : ) Já sám mám radši (i delší) kód nad kterým se neztratím i po delší době.
Chemikus psal hned v prvním postu Nette 2.0, předpokládám tedy nějaký nový build? V downloadech je 14. 10. 2010, což sedí.