Bootstrap modal + Nette form (+Naja)
- Šaman
- Člen | 2659
Ahoj, používám Bootstrap modal pro zobrazení formuláře v modálním okně. Ale po odeslání nechci ihned zavřít modal, protože formulář může být odeslaný chybně (serverová validace). Takže na submit tlačítku nemám navěšený JS pro zavření modalu. Používám snippety, takže s vypsáním validačních chyb není problém – překreslím jen ten formulář.
Mohu ale nějak zařídit zavření modalu až na základě zpracování
formuláře?
Po úspěšném pracování překresluji celou stránku – flashmessage
vyskočí, přesto mi zůstane celá stránka zašedlá a nelze na ni klikat
(jako kdyby přes ni bylo modální okno, které ale není zobrazené). Pomohlo
až vytvořit snippet v samotném tagu
<body n:snippet="body">
. Což není úplně košer –
raději bych překreslil jen flasmessage a modal. Imho zapnutí modalu změnilo
nějaké atributy přímo na <body>
a pouhé překreslení
modalu ho sice skrylo, ale ty změny na <body>
zůstaly.
Máte nějaký osvědčený způsob, jak zpracovat Nette formulář v BS modalu tak, že zavření modálního okna zařídí překreslení snippetu?
Díky.
P.S. Používám Naju, ale v tomto se používá jen pro snippety. Modal je na ní zcela nezávislý.
Editoval Šaman (28. 1. 2021 8:06)
- lookass
- Člen | 54
Ahoj, vím, že se ptáš na Naju, ale nikdo nereagoval, tak bych si dovolil napsat, že Nittro tohle umí. Návod i příklad je na Nittro fóru
- medhi
- Generous Backer | 255
Ahoj, stačí po úspěšném zpracování formuláře poslat
$this->payload->closeModal = true;
a do svého JS si dopsat
toto zpracování, které modal zavře:
naja.addEventListener('success', event => {
if (typeof event.detail.payload.closeModal !== 'undefined') {
$('#myModal').modal('hide');
}
});
Píšu to z hlavy, tak dej vědět, kdyby to nešlo, ale snad je jasný princip.
- monty
- Člen | 66
Ahoj.
Prosím pěkně, nedaří se mi zachytit Najou odeslání
formuláře ve vyskakovacím modalu (dokresleným taktéž ve snippetu
přes ajax).
// Přesedlal jsem z nette.ajax knihovny, kde jsem po vykreslení modalu volal...
$.nette.load();
naja.initialize(); // Mi vyhodí exception.
//Zkusil jsem teda naprasáka...
delete naja.initialized; //...ale to se rozbije uplně všechno :c)
Díky za radu :)
- Šaman
- Člen | 2659
Já to mám ještě rozkopaný, pak jsem chtěl dát na GitHub celou ukázku projektu. Ale jestli myslíš ajaxové odeslání formuláře, pro to jsem nic dělat nemusel. Mám Naju 2 a v základu jediné co potřebuji je
document.addEventListener('DOMContentLoaded', () => naja.initialize());
O chlup slozitější bylo až ovládání toho modal okna.
- jiri.pudil
- Nette Blogger | 1029
Naja se na .ajax
elementy v překreslených snippetech
znovu-navěšuje sama, není potřeba nic volat. Pokud ale otevíráš modal
nějakým javascriptem, je možné, že to v DOMu vyrobí nové elementy,
o kterých Naja neví. V takovém případě budeš muset ajaxové chování
navěsit ručně.
- Pepino
- Člen | 256
@vb76 Muzes v payloadu po uspesnem zpracovani formulare poslat napr closeModal=true a poladit si prekresleni snippetu https://naja.js.org/#…
Editoval Pepino (4. 4. 2022 19:56)
- vb76
- Člen | 16
Pepino napsal(a):
@vb76 Muzes v payloadu po uspesnem zpracovani formulare poslat napr closeModal=true a poladit si prekresleni snippetu https://naja.js.org/#…
Jde mi spíše přímo o toto:
Ale po odeslání nechci ihned zavřít modal, protože formulář může být odeslaný chybně (serverová validace).
Pokud dojde k chybě, kterou předám přes $form->addError modal se po odeslání zavře. Když ho znovu otevřu, je formulář vyplněný, chyba zobrazena. Ale já nechci, aby se zavíral, když obsahuje info o chybě.
Hledám nějaké info, jak zamezit zavíraní modalu, když je zobrazena nějaká chyba. Pokud vše proběhne v pořádku, modal se zavře a obsah inputů vymaže. To je žádoucí a to mám vyřešené.
- vb76
- Člen | 16
Pepino napsal(a):
@vb76 zpracovavas ten formular v modalu ajaxem?
V modalu na form mám třídu ajax. Na formulář je vytvořena továrna a je v BasePresenter. Jedná se o registrační formulář, který je možné zobrazit na jakékoliv stránce.
Nicméně se to chová podobně i bez ajaxu, pokud bych ho nechtěl použít. Potřebuji asi jen nakopnout, jakým směrem jít. Třeba ověřuji e-mail na chybném místě v nesprávnou dobu. Takhle to mám zažité, ale modal pro formuláře používám poprvé.
Ve zpracování formuláře, po úspěšné validaci, ověřuji e-mailovou adresu v databázi. Pokud existuje, nastavím $form->addError().
$form->onSuccess[] = function (Form $form, \stdClass $data) use ($onSuccess): void
{
if($this->user->checkEmail($data->iEmail))
{
$form->addError('E-mailová adresa již v systému existuje!');
}
else
{
$this->user->add($data);
}
$onSuccess();
};
Formulář se odešle, modal zavře, ale obsahuje info z $form->addError(‚E-mailová adresa již v systému existuje!‘); Poku formulář znovu otevřu, je vše správně, ale já nechci, aby se zavíral, pokud obsahuje chybu. Potřebuji tomu nějak zamezit a vůbec netuším kde hledat, jakým směrem jít.
Editoval vb76 (4. 4. 2022 21:50)
- Pepino
- Člen | 256
@vb76 třídu ajax tam mít můžeš, ale otázka jestli se ti formulář ajaxem zpracovává.
Ověření emailu dej přímo na políčko iEmail.
$form->addEmail('iEmail')
->addRule(function($control) {
return $this->user->checkEmail($control->value)
}, 'E-mailová adresa již v systému existuje!')
- vb76
- Člen | 16
Pepino napsal(a):
@vb76 třídu ajax tam mít můžeš, ale otázka jestli se ti formulář ajaxem zpracovává.
Ověření emailu dej přímo na políčko iEmail.
$form->addEmail('iEmail') ->addRule(function($control) { return $this->user->checkEmail($control->value) }, 'E-mailová adresa již v systému existuje!')
Děkuji za TIP. Nicméně to problém se zavíráním modalu nevyřešilo. Toto pravidlo se stejně zavolá až po odeslání formuláře. To znamená, že bez ajaxu se problém nepodaří vyřešit…
Původně jsem si myslel, že se nejprve provedou javascriptová pravidla na straně klienta, pak se zpracuje onValidate a až pak se odešle formulář a zpracuje se onSuccess.
- Pepino
- Člen | 256
@vb76 pokud nebudeš ten formulář zpracovávat ajaxem tak se ti vždycky ten modal zavře.
Ano první se provedou javascriptová pravidla, pokud jsou v pořádku
formulář se odesílá a přechází se k serverové validaci. Pokud
serverová validace projde přechází se k onSuccess
. Ale tady
jsme opět u toho. Pokud nezpracováváš ajaxem tak javascript prostě
neověří jestli zadaný email už existuje nebo ne.
- Petr Parolek
- Člen | 455
Petr Parolek napsal(a):
@mbrecher tady je ukázka https://github.com/…test-project .
Ahoj, nevíte, jak prosím upravit kod, aby v odkazu
Launch edit form in modal
nebyl parametr isModal
?
- Pepino
- Člen | 256
Petr Parolek napsal(a):
Petr Parolek napsal(a):
@mbrecher tady je ukázka https://github.com/…test-project .
Ahoj, nevíte, jak prosím upravit kod, aby v odkazu
Launch edit form in modal
nebyl parametrisModal
?
HomepagePresenter.php
Tohle smaž:
public function beforeRender(): void
{
if ($this->isAjax() && (bool) $this->getParameter('isModal')) {
bdump('isAjax');
$this->payload->showModal = true;
$this->payload->modalId = 'myModal';
$this->redrawControl('modal');
}
}
Tohle přidej:
public function actionEdit(): void
{
if ($this->isAjax()) {
$this->payload->showModal = true;
$this->payload->modalId = 'myModal';
$this->redrawControl('modal');
}
}
- Petr Parolek
- Člen | 455
@Pepino nefunguje dobře modal se zavře, ale nezmizi v html:
<div class="modal-backdrop fade show"></div>
takže stránka zůstává napůl průhledná a stránku nelze ovládat.
Přikládám diff dle tvé rady:
diff --git a/app/Presenters/HomepagePresenter.php b/app/Presenters/HomepagePresenter.php
index ca3e969..e428162 100644
--- a/app/Presenters/HomepagePresenter.php
+++ b/app/Presenters/HomepagePresenter.php
@@ -15,10 +15,9 @@ final class HomepagePresenter extends Presenter
*/
public $database;
- public function beforeRender(): void
+ public function actionEdit(): void
{
- if ($this->isAjax() && (bool) $this->getParameter('isModal')) {
- bdump('isAjax');
+ if ($this->isAjax()) {
$this->payload->showModal = true;
$this->payload->modalId = 'myModal';
$this->redrawControl('modal');
@@ -33,9 +32,7 @@ final class HomepagePresenter extends Presenter
$form->addSubmit('ok', 'OK');
- $isModal = (bool) $this->getPresenter()->getParameter('isModal');
-
- if ($isModal && $this->getPresenter()->isAjax()) {
+ if ($this->getPresenter()->isAjax()) {
$form->getElementPrototype()->class('ajax');
}
diff --git a/app/Presenters/templates/Homepage/default.latte b/app/Presenters/templates/Homepage/default.latte
index cafbb11..11c5acd 100644
--- a/app/Presenters/templates/Homepage/default.latte
+++ b/app/Presenters/templates/Homepage/default.latte
@@ -8,7 +8,7 @@
{control itemsForm}
{/snippet}
-<a n:href="Homepage:edit, isModal => 1" class="btn btn-outline-info ajax">Launch edit form in modal</a>
+<a n:href="Homepage:edit" class="btn btn-outline-info ajax">Launch edit form in modal</a>
<!-- Button trigger modal -->
<button type="button" class="btn btn-outline-info" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
Editoval Petr Parolek (29. 9. 2022 13:55)
- Petr Parolek
- Člen | 455
@Pepino schová, ale stále ne úplně viz obrázek https://ctrlv.cz/BpXB
Editoval Petr Parolek (29. 9. 2022 16:53)
- Pepino
- Člen | 256
@PetrParolek
openModal(event) {
let payload = event.detail.payload;
if (payload === null || !payload.hasOwnProperty('modalId')) {
return;
}
let modalId = payload.modalId;
let showModal = payload.showModal;
if (showModal === undefined || showModal === false) {
$(".modal-backdrop").remove();
$('body').removeClass('modal-open').removeAttr('style');
return;
}
if ($(".modal-backdrop").length > 0) {
$(".modal-backdrop").remove();
$('body').removeClass('modal-open').removeAttr('style');
}
$("#" + modalId).modal('show');
}
A v HomepagePresenter.php
createComponentTestForm
tohle
if ($isModal && $this->getPresenter()->isAjax()) {
$form->getElementPrototype()->class('ajax');
}
nahradit tímhle
if ($this->getPresenter()->isAjax()) {
$form->getElementPrototype()->class('ajax');
}
Editoval Pepino (29. 9. 2022 18:09)
- Petr Parolek
- Člen | 455
Díky moc, funguje, jak má, ikdyž se mi zdá kod prasácký v JS, ale asi
to jinak nejde https://github.com/…03f527d57d6e
. Taky jsem měl rozepsané stejné řešení, ale stále jsem doufal, že
půjde použít nějak $("#" + modalId).modal('hide');
Editoval Petr Parolek (29. 9. 2022 18:44)
- Pepino
- Člen | 256
@PetrParolek Jinak to nejspíše nejde. Já mám svoje řešení
trošku jiné ale (bs5, odstraněný neduh problíkávání) ale taky to není
podle mě úplně čisté. Problém tam je v tom, že když se překreslí
snippet s modalem, tak ztratí modal ztratí info o tom, že je vykreslený a
nejde tím pádem použít modal('hide')
. U mojeho řešení ho
sice používám, ale je potřeba „ručně“ modalu říct, že je
vykreslený a inicializovaný. Jestli budeš chtít tak to tu postnu.
- Petr Parolek
- Člen | 455
Napadlo mě udělat něco takového:
<a data-href="{link Homepage:edit, isModal => 1}" n:href="Homepage:edit" class="btn btn-outline-info ajax ajax-href">Launch edit form in modal</a>
Ale nevím, jak upravit JS, aby nebral odkaz z href ale z data-href-
- Petr Parolek
- Člen | 455
@Pepino ještě jednou díky, moc jsi mi pomohl – https://github.com/…oject/pull/2 , toto řešení je pecka.