Nette Ajax a bootstrap modal
- d@rkWolf
- Člen | 167
Zdravím, snažím se implementovat do administračního rozhraní našeho systému otevírání některých editačních formulářů do modálních oken, vycházel jsem tady z tohoto tématu: https://forum.nette.org/…im-okne-ajax , ale narazil jsem na problém s překreslováním obsahu(snippetu s tabulkou) v presenteru, z kterého modal otvírám, který nemůžu vyřešit, kdyby někdo prosím dokázal poradit, co dělám špatně, nebo jestli je to úplně neřešitelná varianta.
Hlavní @layout.latte backendu(kód bootstrap Modalu ve snippetu):
<?php
{snippet modal}
{if $presenter->isAjax()}
{ifset #modal}
<div class="modal fade modal-ajax" id="remoteModal" tabindex="-1" role="dialog" aria-labelledby="remoteModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
{block modalHeader}
<h4 class="modal-title">{block|striptags}{include #title}{/block}</h4>
{/block}
</div>
<div class="modal-body">
{include #modal}
</div>
{ifset #modalFooter}
<div class="modal-footer">
{include #modalFooter}
</div>
{/ifset}
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
{/ifset}
{/if}
{/snippet}
?>
JS kód(vypnut výchozí ne-ajaxový redirect extension nette.ajax):
<script>
$.nette.ext('redirect', false);
$.nette.ext("modals", {
success: function(payload) {
if (payload.redirect) {
$(".modal-ajax").modal("hide");
$('body').removeClass('modal-open');
} else if(payload.isModal) {
$('.modal-ajax').modal('show');
}
}
});
$.nette.ext("ajaxRedirect", {
success: function (payload) {
if (payload.redirect) {
$.nette.ajax(payload.redirect);
}
}
});
</script>
Presenter s modalem(v modalu se otvírá komponenta s formulářem), default šablonu presenteru sem asi dávat nemusím, není tam nic zvláštního, popup se otvírá n:href odkazem „presenter:addPopup“ a běžná tabulka je obalená snippetem „popupList“:
<?php
protected function createComponentPopupFormControl() {
return new \PopupFormControl($this, 'popupFormControl', $this->popupsRepository);
}
public function actionAddPopup () {
if ($this->isAjax()) {
$this->payload->isModal = true;
$this->redrawControl('modal');
}
}
public function actionEditPopup($id) {
/** @var \App\Popups $popup */
$popup = $this->popupsRepository->popups->find($id);
$this->template->popup = $popup;
$form = $this['popupFormControl']['popupForm'];
...nadefinování výchozích hodnot editačního formuláře atd...
if ($this->isAjax()) {
$this->payload->isModal = true;
$this->redrawControl('modal');
}
}
?>
šablona addPopup.latte:
<?php
{block title}Přidat Pop-up{/block}
{block content}
<section>
...běžné html nutné k naformátování do admin šablony...
{block modal}
{control popupFormControl}
{/block}
...
</section
?>
Komponenta:
<?php
class PopupFormControl extends Control {
public function __construct(\Nette\ComponentModel\IContainer $parent = NULL, $name = NULL, \App\PopupsRepository $popupsRepository) {
parent::__construct($parent, $name);
$this->popupsRepository = $popupsRepository;
}
protected function createComponentPopupForm() {
nadefinování formuláře...
}
public function popupFormSubmitted(Form $form) {
zpracování formuláře
if ($this->presenter->isAjax()) {
$this->presenter->payload->closeModal = true;
$this->presenter->payload->isModal = false;
****
$this->presenter->redrawControl('popupList');
****
$this->presenter->redrawControl('modal');
} else {
$this->presenter->redirect('Settings:');
}
}
?>
Zde ve zpracování formuláře v komponentě jsem chtěl, aby se překreslil popupList snippet(tabulka v presenteru, aby se přidal nový řádek/upravil obsah podle akce v modalu), což se neprovede, do ajaxu se snippet popupList nevloží, pouze snippety modal a flashes
Šablona komponenty(jen formulář):
<?php
{form popupForm}
...mám tu manuální vykreslení kvůli specifickému formátování admin šablony...
{/form}
?>
Ve chvíli, kdy to mám takto funguje otevření modalu, zavření modalu, uložení a editace údajů, ovšem po zavření modalu se nepřekreslí tabulka v Presenteru, takže uživatel neví(kromě infa z Flashes, to se zobrazí), vizuálně nevidí, že se položka, kterou ukládal opravdu uložila/změnila, protože se nepřekreslí snippet popupList.
Zkoušel jsem i druhou variantu, kdy vyřadím redrawControl ze zpracování formuláře v komponentě, umístím tam redirect(ajaxový) a redrawControl místo toho umístím do beforeRender() metody presenteru:
<?php
public function beforeRender() {
if ($this->isAjax()) {
$this->redrawControl('modal');
$this->redrawControl('popupList');
}
}
?>
V tomto případě nastane po uložení formuláře v modalu ajaxový redirect zpět na presenter a položky se překreslí, bohužel při této variantě mi to překresluje zmíněné snippety stále, při každém ajax požadavku v tomto presenteru a těchto požadavků je tam víc, protože je to presenter, v kterém je řada samostatných nastavení pro konfiguraci systému a většina se zpracovává ajaxově a já nevím, jak v tom beforeRender() omezit to zpracování jen na případ, kdy jde opravdu o překreslení po zpracování toho modalu, protože pokud ukládám něco úplně jiného, vůbec nepotřebuju, aby se mi překreslovaly snippety, které s tím nesouvisí. Nemůžu přijít na to, jak ten požadavek odlišit od jiných.
- d@rkWolf
- Člen | 167
@Felix v tomhle je jen jeden snippet – {snippet modal} a do toho
se includují bloky z jiné šablony(addPopup.latte nebo edidPopup.latte) ,
snippet {popupList} se seznamem položek není uvnitř toho modalu, takže to by
teoreticky neměla být situace pro snippetArea, nebo se to týká
i includovaného obsahu, který není uvnitř dalšího snippetu? samotný
formulář už v dalším snippetu obalený není.
Nicméně musím říct, že snippetArea moc nerozumím, nikdy jsem to
nepoužil/nepotřeboval/nevěděl že potřebuju.