Po upgrade Nette na 2.4 se akce chová jinak a vyžaduje šablonu

milanb
Člen | 64
+
0
-

Ahoj,
udělal jsem upgrade z v 2.3 na 2.4 apliakce, kterou jsem původně nepsal. Ve formuláři obsluhuju tlačítko pomocí signálu editAction:
<a href="/actions/default/165/?do=editAction&amp;admin=0">Uložit</a>

V JavaScriptu je pak funkce editActionClick: function(event), která pro aktualizaci dat používá POST:
$.post('/actions/save/' + action,... (action je ID záznamu, který se má aktualizovat).

Funkce presenteru pro obsluhu akce save je actionSave($id) ve svém těle pracuje s DB a na konci vytvoří Latte objekt podle šablony ActionsList.latte:

$latte = new Latte\Engine;
$latte->render(__CONTROL__ . '/actions/ActionsList.latte', [...

V případě úspěchu POST requestu se v JS volá .done(my.editActionSuccess), a ta aktualizuje obsah fragmentu stránky pomocí této JS funkce:

editActionSuccess: function( data )
{
  $('#actions-list').html($(data).html());

Funkce v JS editActionSuccess se tedy snaží nahradit obsah <div id=actions-list> tím, co vrátil POST request – vygenerované HTML. V konzole jsme si ho nechal vypsat a fakt tam je.

Až k tomuto místu vše chápu a funguje to. Pak se ale něco v běhu aplikace ještě dál řeší a tam mě Tracy vyhodí chybu:
Missing template 'D:\TEMP\_0repos\magnusys\app\presenters\templates\Actions\save.latte'.

Problém je asi v tom, že se pomocí toho POST zavolá akce presenteru /actions/save/165 (ID 165 jsem dal jako příklad), asi by se to mělo volat jinak, ne jako akce., ale nevím, jak.

Díky za každou radu, co s tím…

Editoval milanb (19. 3. 18:05)

m.brecher
Generous Backer | 763
+
0
-

@milanb

missing template …\app\presenters\templates\Actions\save.latte

Presenter se pokusí načíst defaultní šablonu akce save, což Ty nepotřebuješ.

Protože request odesíláš ajaxově, měl by se v akci presenteru ajaxově zpracovat. Tj. odeslat html snippet, který máš v __CONTROL__ . ‚/actions/ActionsList.latte‘ pomocí standardní metody Nette pro ajax sendJson(). Pokud presenter odešle request pomocí sendJson() tak potom šablonu akce už nehledá.

Jinou možností je po volání $latte->render() ukončit činnost presenteru $this->terminate(), ale to je nouzové řešení.

Šaman
Člen | 2635
+
0
-

Moc tomu nerozumím, vypadá to, že všechno obchází pohodlné nativní funkce Nette.
Ale samotná metoda actionSave se nic vykreslit nesnaží a pokud tady provedeš nějaké překreslení, nebo ukončení presenteru, šablonu to po tobě chtít nebude. K tomu dojde až PO action, když se zkouší render.
Imho by stačilo vytvořit metodu renderSave($id), kde jen nastavíš soubor s šablonou (neměl bys ji vytvářet ručně a pokud ten soubor bude na standardním místě a správně pojmenovaný, načte se sám a není nutná ani ta prázdná render metoda). Pokud to voláš opravdu z presenteru.

Pokud to ale chceš zachytit a vykreslit po svém v actionSave($id), mělo by to fungovat. Zkus případně po tom render() dát ještě řádek $this->terminate(); A uvidíš jestli se něco vykreslilo, nebo to nedohledalo ten ActionsList.latte.

milanb
Člen | 64
+
0
-

Zkusím nejdřív sendJson(). Pak zkusím renderSave($id). Taky mě napadlo z toho JS nevolat action, ale opět AJAX handler, když už je hotový ten kód na vytvoření HTML ze šablony.
Díky moc.

m.brecher
Generous Backer | 763
+
0
-

@milanb

. Taky mě napadlo z toho JS nevolat action, ale opět AJAX handler

Ano, lepší by bylo použít pro komunikaci signál editAction, který tam už máš:

<a href="/actions/default/165/?do=editAction&amp;admin=0">Uložit</a>

a potom se javascriptem přesměruje na jinou akci – z akce default na akci save:

$.post('/actions/save/' + action,... (action je ID záznamu, který se má aktualizovat).

Měl by Jsi si vytvořit handler signálu a v něm volat metodu save() modelové třídy, to by bylo lepší.

Z Nette odesílat html snippet pomocí sendJson() a akci presenteru save vůbec nepoužívat.

Poznámka k názvosloví:

action je ID záznamu

lepší je pro ID záznamu použít jméno parametru id

do=editAction

nepoužívat pro jména signálů suffix Action, handler signálu by potom byl handleEditAction(), což se může plést s akcemi presenteru, lepší by bylo použít pro signál jméno edit! a handler handleEdit()

milanb
Člen | 64
+
+1
-

Ahoj, díky moc všem za pomoc, už se i podařilo upgradovat z 2.3 na 3.1, už zbává jen kousek cesty k 3.2… :-)