Nette Ajax a bootstrap modal

d@rkWolf
Člen | 167
+
+1
-

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">&times;</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.

Felix
Nette Core | 1196
+
0
-

Ahoj @d@rkWolf,

jestli to chapu dobre, tak mas snippet, ve kterem mas modal a v tom modale formular, ktery je taky ve snippetu?

Mozna by to vyresila snippetArea, ktera je potreba, kdyz je snippet ve snippetu. Nezkousel jsi?

d@rkWolf
Člen | 167
+
0
-

@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.