Snippety uvnitř forumláře
- monty
- Člen | 66
Šaman napsal(a):
Ne (resp. nevím o tom). Ale můžeš si upravit (nebo napsat vlastní) renderer.
No, popravdě jsem to už zkoušel, ale nepodařilo se mi přijít na to, jak
se přes renderer dostat přímo ke control prvku.
Myslel jsem tedy, že přes něj můžu ovlivnit jen vykreslování
nadřazených kontejnerů.
Mohl bys mě prosím trochu nasměrovat?
- Šaman
- Člen | 2663
Plánuji si to do rendereru zakomponovat, ale zatím aspoň pro představu: takhle si přidávám bootstrap přílepky (zleva nebo zprava) k inputu.
<?php
public function renderControl(Nette\Forms\IControl $control)
{
$this->controlsInit();
$inputGroup = $this->getWrapper('input-group container');
if ($control->getOption('input-group-prefix')) {
$prefix = '<div class="input-group-addon">' . $control->getOption('input-group-prefix') . '</div>';
}
elseif ($control->getOption('input-group-prefix-glyphicon')) {
$prefix = '<div class="input-group-addon">'
. '<span class="glyphicon glyphicon-'
. $control->getOption('input-group-prefix-glyphicon')
. '" aria-hidden="true"></span>'
. '</div>';
}
else {
$prefix = '';
}
if ($control->getOption('input-group-suffix')) {
$suffix = '<div class="input-group-addon">' . $control->getOption('input-group-suffix') . '</div>';
}
elseif ($control->getOption('input-group-suffix-glyphicon')) {
$suffix = '<div class="input-group-addon">'
. '<span class="glyphicon glyphicon-'
. $control->getOption('input-group-suffix-glyphicon')
. '" aria-hidden="true"></span>'
. '</div>';
}
else {
$suffix = '';
}
.
.
.
if (!empty($prefix) || !empty($suffix)) {
$el = $inputGroup->setHtml($prefix . $el . $suffix);
}
return $body->setHtml($el . $this->renderErrors($control));
?>
A použití je:
<?php
$form->addText('personalId', 'Osobní číslo')->setOption('input-group-prefix', "foo");
?>
Pro obalení samotného controlu snippetem to bude skoro stejné. To jméno
snippetu bych negeneroval automaticky z názvu prvku (i když i ten by měl
jít dohledat), ale pomocí nějaké vlastní
option ->setOption('snippet', "fooBar")
Editoval Šaman (16. 1. 2018 0:01)
- monty
- Člen | 66
@Šaman
To je paráda, chystám se řešit úplně to samý :)
Takže díky, zkusím zakomponovat tvůj návrh.
Snippety nad control řeším kvůli dynamickému selectu, abych nemusel překreslovat celý formulář po načtení jeho hodnot z databáze. Protože po překreslení přijde uživatel o už zadané hodnoty.
Zatím jsem to ale vyřešil takovou „oklikou“, před ajaxem si načtu data a po načtení je zase do inputů vrátím.
No a jméno snippetu jsem chtěl generovat automaticky, protože v aplikaci budu muset určitě použít nějaký replikátor a tam zadávat jméno snippetu ručně nebudu určitě. Ale to budu řešit, až k tomu dojde a napadá mě, že by to snad v presenteru nějak napůl generovat šlo.
Přišel jsem teď ale na zásadnější problém.
Po překreslení snippetu, ve kterém je formulář, se po kliknutí na submit
formulář neodešle.
Resp. ajax request proběhne, ale očividně se nezavolá funkce onSubmit.
Nesetkal si se s tím?
Hledal jsem na foru a ptal se Googla, ale nic, co by mi pomohlo jsem
nenašel.
- Šaman
- Člen | 2663
Aha, nesetkal, mě zase přestal fungovat ajax. Takže se to odešle, zpracuje, ale neajaxově. Zkouším s tím pohnout, kdyžtak dám vědět.
- monty
- Člen | 66
Tak to mě mrzí, že máme takový trable s formulářema, s onError bohužel zatím vůbec nepracuju.
Ta moje chyba ajaxem není.
Zjistil jsem, že i když forumlář neodesílám přes ajax, tak po
překreslení jeho snippetu se po kliknutí na submit jen refreshne
stránka.
Tak pokud něco zjistíš, prosím napiš, já se bez tohodle nehnu :/
Zkusím ještě hodit dotaz do začátečníků, protože tam prozatím
spadám :)
- Šaman
- Člen | 2663
Zkus si tenhle
minimalizovaný příklad se závislými inputy.
Nenapadá mě moc kde by mohla ztratit obsluha onSuccess. Navázaný ajax
můžeš při překreslení ztratit proto, že nový (překreslený) prvek už
není TEN prvek, na který jsi navázal událost. Ale samotné neajaxové
odeslání formuláře by mělo být bez problémů, pokud neměníš ID,
případně NAME atribut odesílacího tlačítka. Server se ani nedozví, že
se formulář na klientu překreslil.
- monty
- Člen | 66
No v tomhle příkladu je právě ve snippetu obalený přímo ten
input.
To je právě to, čeho se snažím docílit, ale bez toho, aniž bych musel
manuálně vykreslovat.
Zkusím ještě pozměnit ten renderer, podle tvýho návrhu.
Tím by se pak asi zabili dvě mouchy jednou ranou, protože by se
nepřekresloval celý formulář a tím pádem bude fungovat submit.
Pokud se mi to s tím rendererem nepovede, napadla mě ještě varianta, že si
budu podle zadání načítat ajaxem JSON a z toho si pak překreslím select
čistě pomocí JS.
- David Matějka
- Moderator | 6445
ahoj, snippety bez manualniho renderovani myslim nijak (snadno) nezprovoznis. snippety jsou uzce provazany s latte
- monty
- Člen | 66
@DavidMatějka
Ahoj Davide.
Prima, díky za objasnění.
Prosím tě, jsi jeden z nejpovolanějších, takže určitě budeš
vědět.
Existuje možnost, pokud budu chtít dynamicky přidávat a odebírat prvky
formuláře pomocí JS, jak je při tom přes handle inicializovat/odpojovat
tak, aby všechno fungovalo jak má a Nette je viděl nebo s nima případně
nepočítal?
Nebo to bez nějakého replikátoru prostě řešit nejde?
- David Matějka
- Moderator | 6445
@monty muzes jit cestou low level formularu, kdy pri zpracovani obchazis nejake validacni mechanismy nette. ale nejaky replikator je obvykle lepsi cesta.
- Šaman
- Člen | 2663
Tak potvrzuji, že renderer na snippety nejspíš jednoduše nejde. Dokážu
si vyrenderovat ať už <div n:snippet="foo">
okolo inputu,
nebo <div id="snippet--foo">
, výsledné html je identické,
ale v přeložené šabloně (v cache) chybí obsluha těchto snippetů
(vygenerovaná function blockFoo($_args)
).
A to jsem neřešil dynamicky vygenerovaná pole formuláře, ale přímo
ručně řečené, které inputy chci obalit snippetem.
Editoval Šaman (16. 1. 2018 16:45)
- monty
- Člen | 66
Nuže.
Vykreslil jsem si manuálně formulář, obalil jsem select snippetem a stále
ta samá chyba…submit…refresh…nic.
Dle rady @Mortisson jsem přidal onError a ejhle, přece jen
něco…„This field is required.“ a po dumpu hodnot, jsem
zjistil, že překreslený select je podle všeho null.
Jsem už z toho úplně tumpachovej a nejradši bych utekl někam do jeskyně.
Můžete na to prosím Vás někdo hodit oko?
Nahrál jsem to všechno na GIT.
- Šaman
- Člen | 2663
Vždyť v tom handleru nenastavuješ values toho formuláře. To, že je
vykreslíš neznamená, že ty hodnoty fomulář zná. Přijdou mu nějaké
neznámé hodnoty a on je zahodí jako podvržené.
Buď to tedy udělej jako v tom mém příkladu, ten funguje.
Anebo to udělej přes low-level formuláře, které ti odkazoval David. To je
totiž přesně to, co děláš (vykreslíš v šabloně inputy, které objekt
$form nezná, takže je neumí zpracovat).
- monty
- Člen | 66
To mi ale nejde do hlavy.
V tom handleru si přece nastavuju class property, podle který se
i nastavují prvky formuláře (výchozí radio a hodnoty selectu).
Na tvůj příklad jsem se koukal.
Zkoušel jsem i v handleru nastavit hodnoty pro select pomocí setItems(), ale
i tak to nešlo.
Napadá mě ale, že to bylo možná tou property se kterou i nadále
továrnička pracovala.
Zkusím to večer ještě překopat.
- Matouš Trča
- Člen | 1
Ahoj, nakonec jsem vymyslel následující workaround, pokud to ještě
někoho zajímá. Nepoužívá se redrawControl
, pouze se simuluje
chování této metody. Lepší fungující řešení jsem na fóru
nenašel.
public function handleChange(): void
{
$fileSelect = $this['articleForm']
->getComponent('files')
->setItems([...]);
$this->payload->snippets = [
$fileSelect->getHtmlId() => (string) $fileSelect->getControl()
];
}