Sortable a AJAXový požadavek
- BaruCepa
- Člen | 33
Zdravím znovu, do administrace svého projektu jsem zakomponovala funkci jQuery UI Sortable, ta mi funguje krásně. Ale nejsem schopná k tomu napasovat AJAXový požadavek, který by změnu pořadí poslal zpět, abych ji mohla pak reflektovat v databázi a tam uložit nové pořadí. Prošla jsem zde starší dotazy podobného typu, ale nejsem z nich úplně moudrá. Prosím o radu, jak si s tím poradit. Na projektu používám i Docker.
Soubor admin.js:
$("#sortable-list").sortable({
update: () => {
const sortedIDs = $( "#sortable-list" ).sortable( "toArray" );
$.ajax({
url: "/Administration/changeOrder",
data: {
"sortedIDs" : sortedIDs,
}
});
}
});
Handler v presenteru:
public function handleChangeOrder(array $sortedIDs)
{
if ($this->isAjax())
{
$this->sendJson(['result' => $sortedIDs]);
}
else
{
$this->error('Toto není AJAXový požadavek.');
}
}
Nyní je to ve fázi, kdy sortable funguje krásně, ale dle DevTools nedojde k použití handleru. Při přesunu položky debugovací lišta zobrazí AJAX, ale se špatným presenterem i šablonou. Nový seznam se nejspíš vrací i jako GET, takže je varianta to nějakým způsobem vypreparovat z toho?
- Infanticide0
- Člen | 64
url: „/Administration/changeOrder“ neni link na signál a natvrdo v šabloně bych ho radil nemít (změníš název handle funkce a přestane to fungovat), vytvoř si link přes presenter ($this->link(„change!“)) a předej jako template proměnnou do šablony, tam ji vypiš v data-url=„{$x}“, to pak čti javascriptem a použij v ajax requestu.
bez zbytečnýho zanořování kódu:
public function handleChangeOrder(array $sortedIDs)
{
if (!$this->isAjax())
$this->error('Toto není AJAXový požadavek.');
$this->sendJson(['result' => $sortedIDs]);
}
Editoval Infanticide0 (16. 12. 2023 19:24)
- BaruCepa
- Člen | 33
@Infanticide0
Dobře, upravila jsem dle tvých připomínek takto:
$("#sortable-list").sortable({
update: () => {
const sortedIDs = $( "#sortable-list" ).sortable( "toArray" );
$.ajax({
url: "{$url}",
data: {
"sortedIDs" : sortedIDs,
}
});
}
});
A presenter :
public function renderDefault()
{
if (!$this->getUser()->isLoggedIn())
{
$this->redirect('Administration:login');
}
else
{
$this->template->username = $this->user->identity->username;
$pages = $this->pageManager->getAllPages();
$this->template->pages = $pages;
$url = $this->link("change!");
$this->template->url = $url;
}
}
public function handleChange(array $sortedIDs)
{
if (!$this->isAjax())
{
$this->error('Toto není AJAXový požadavek.');
}
$this->sendJson(['result' => $sortedIDs]);
}
Ale teď nevím, co dál. Kde vybrat změněné pořadí, abych s ním mohla dál pracovat? S AJAXem si hraju poprvé a úplně ho ještě nechápu.
- Infanticide0
- Člen | 64
Koukni na kód, lepší než to složitě vysvětlovat. Proměnné v Latte nikdy neobaluj do uvozovek, o to se postará Latte samo (mělo by ti vyhodit chybu, když to uděláš).
V příkladu dole by se určitě hodilo ještě validovat data z POSTu, možná by to celý šlo předělat do formuláře, aby to validovalo automaticky.
Presenter:
final class HomePresenter extends Nette\Application\UI\Presenter
{
public function renderDefault(): void
{
$this->template->url = $this->link("changeOrder!");
}
public function handleChangeOrder(): void
{
if(!$this->isAjax())
$this->error("ajax!");
$newOrder = $this->request->getPost("items");
$this->sendJson(['result' => $newOrder]);
}
}
Template:
<ul id="sortable">
<li data-value="1" class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 1</li>
<li data-value="2" class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 2</li>
<li data-value="3" class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 3</li>
<li data-value="4" class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 4</li>
<li data-value="5" class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 5</li>
<li data-value="6" class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 6</li>
<li data-value="7" class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 7</li>
</ul>
<script src="{$basePath}/jquery.js"></script>
<script src="{$basePath}/jquery-ui.min.js"></script>
<link rel="stylesheet" href="{$basePath}/jquery-ui.min.css">
<script>
$(function() {
$("#sortable").sortable({
update: (event, ui) => {
let sortedIDs = $("#sortable").sortable("toArray", {
"attribute": "data-value"
});
$.ajax({
type: "POST",
url: {$url},
data: {
"items" : sortedIDs,
}
}).done(function(response) {
console.log(response.result);
});
}
});
});
</script>
- BaruCepa
- Člen | 33
@Infanticide0
Fuuu, tak jsem prošla, upravila, dosáhla jsem toho, ža už se na Tracy
liště zobrazuje AJAX se správným presenterem (routování), ale pořád
nedojde na handle metodu, vůbec se to k ní nedostane a tím pádem ani do
databáze.
Presenter:
public function renderDefault()
{
if (!$this->getUser()->isLoggedIn())
{
$this->redirect('Administration:login');
}
else
{
$this->template->username = $this->user->identity->username;
$pages = $this->pageManager->getAllPages();
$this->template->pages = $pages;
$this->template->url = $this->link("change!");
}
}
public function handleChange()
{
if (!$this->isAjax())
{
$this->error('Toto není AJAXový požadavek.');
}
$newOrder = $this->request->getPost("items");
$this->pageManager->updatePageOrder($newOrder);
$this->sendJson(['result' => $newOrder]);
}
admin.js :
$("#sortable-list").sortable({
update: () => {
const sortedIDs = $( "#sortable-list" ).sortable( "toArray" );
$.ajax({
url: '{$url}',
type: "POST",
data: {
"items" : sortedIDs,
}
}).done(function(response) {
console.log(response.result);
});
}
});
A přidám i RouterFactory, jestli není pes zakopanej tam :
final class RouterFactory
{
use Nette\StaticClass;
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute('administrace/<action>[/<url>]', 'Admin:Administration:default');
$router->addRoute('<action>[/<url>]', [
'presenter' => 'Admin:Administration',
'action' => [
Route::FILTER_STRICT => true,
Route::FILTER_TABLE => [
'administrace' => 'default',
'prihlaseni' => 'login',
'odhlasit' => 'logout',
]
]
]);
$router->addRoute('<action>[/<url>]', [
'presenter' => 'Admin:Editor',
'action' => [
Route::FILTER_STRICT => true,
Route::FILTER_TABLE => [
'editace' => 'editor',
'ulozeni' => 'save',
'smazani' => 'remove',
]
]
]);
$router->addRoute('<id .*>', [
'presenter' => 'Front:Page',
'action' => 'page',
'id' => 'uvod',
]);
return $router;
}
}
Jinak jak je v admin.js ten console.log, v konzoli je akorát undefined. Jinak nic, žádné chyby, network se tváří taky dobře, všechno 200.
- Infanticide0
- Člen | 64
@BaruCepa
Soubor admin.js ti latte nezpracuje, takže nedosadí tu proměnnou $url,
volá ti to nesmyslnou url?
Nahoře jsem psal o předávání url v templatu stránky, že si ji
přečteš až javascriptem.
Takhle
template:
<ul id="sortable-list" data-url={$url}>
...
admin.js
<script>
$("#sortable-list").sortable({
update: () => {
const sortedIDs = $( "#sortable-list" ).sortable( "toArray" );
$.ajax({
url: $("#sortable-list").data("url"), // načte data-url z #sortable-list
...
</script>
Editoval Infanticide0 (19. 12. 2023 15:13)