JqueryUI Sortable s AJAXem

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Darkry
Člen | 101
+
0
-

Zdravím,
s AJAXem jsem v nette ještě nepracoval a teď jsem potřeboval ukládat výsledky JqueryUI do databáze. Jakmile se mi podaří rozchodit handle (i s parametry) tak se serverovou částí už není problém, ale prozatim se mi to nepodařilo.

V presenteru mám prozatím:

public function handleUpdateSort($items) { //UPRAVIT PARAMETRY??
        if($this->isAjax()) {
                   die();
        invalidateControl('sortable');
        }
    }

A v šabloně pak mám:

{snippet sortable}
<ul id="sortable">
<li id="{$item["id"]}">{$item["name"]}</li>
...
</ul>
{/snippet}

A pak jsem našel JS jak to propojit s AJAXem:

<script>
$(document).ready(
	function() {
		$("#sortable").sortable({
			update : function () {
				serial = $('#sortable').sortable('serialize');
				$.ajax({
					url: {link updateSort!},
					type: "post",
					data: serial,
					error: function(){
						alert("theres an error with AJAX");
					}
				});
			}
		});
	});
</script>

Takto to mám nyní bohužel to ale asi bude špatně, protože to nefunguje. Je tam několik věcí u kterých vůbec nevím:

  1. Jak mám přijmout data od AJAXu (přes parametr nebo je načítat z Postu a jak se budou jmenovat?)

2)Jaký bude tvar dat?

JavaScript jsem převzal odsud.

Kromě jQuery mám ještě připojeny tyto doplňky:
netteForms a Ajax s jQuery

Díky za pomoc

Editoval Darkry (18. 7. 2011 16:22)

Bernard Williams
Člen | 207
+
0
-

Nazdárek,

já místo metody POST používám GET a pak data získám pomocí:

$items = $this->getParam('item');

a data procházím obyčejným foreach cyklem:

foreach (items as $index => $value) {
    $db->query('...');
}

Jinak tvar dat si můžeš zobrazit sám:

alert(serial);

Jinak doporučuji odstranit to die(); – s tím ti to asi nepůjde korektně. Dále doporučuji přidat nějakou flash message, aby jsi měl jistotu, že to skutečně proběhlo v pořádku – když se zobrazí → OK, když ne – ERROR. Pořadím těch prvků v tom snippetu to hned nemusíš zjistit, protože nebudeš vědět, jestli to pořadí je správně načteno z DB (snippet se skutečně tak načetl) nebo to změnilo jQuery jen na straně klienta.

Bernard

Darkry
Člen | 101
+
0
-

Problém je, že se žádná data neodešlou → když dám alert(serial); tak se mi vypíše prázdný alert. A hned po prázdném alertu se mi objeví další hláška: „theres an error with AJAX“ (Chyba serveru 500) – ale to bude asi spojený s tim, že se data neodešlou.
Také to může být tím, že sice mám $items = $this->getParam('item');, ale nevim jak se to bude jmenovat ty data → pod jakým jménem se to v getu odešle.

Ani
Člen | 226
+
0
-

Nedávno jsem potřeboval něco podobného, tak jsem zbastlil tohle:

<script>
$(document).ready( function () {
	$(".sortable").sortable({
		items: "td",

		update: function(event, ui) {
			$.get("{link 'selectOrder!'}&move=" + $(ui.item).attr('id')+ "&order=" + $(this).sortable('toArray').toString());
		}
	}).disableSelection();
});
</script>
<?php
	/**
	 * Rebuild order of image
	 *
	 * @param int $move id of moving image
	 * @param string $order order off all image (12,5,6,8,....)
	 */
	public function handleSelectOrder($move, $order) {
		$prev = NULL;
		foreach (explode (',', $order) as $value){
			if ($move == $value){
				break;
			}
			$prev = $value;
		}
		$this->model->moveAfter($move, $prev);
		$this->invalidateControl('gallery');
	}
?>
Darkry
Člen | 101
+
0
-

Díky.

Zkusil jsem sesmolit toto:

<script>
$(document).ready( function () {
        $("#sortable").sortable({
                update: function(event, ui) {
                        $.get({link 'updateOrder!'}+"&id=" + $(ui.item).attr('id')+ "&order=" + $(this).sortable('toArray').toString());
                }
        });
});
</script>
public function handleUpdateOrder($id, $order) {
    $i = 0;
        foreach (explode (',', $order) as $value) {
            $i++;
               MenuModel::updateOrder($value, $i);
        }
}

Ovšem ani to mi nefunguje. JS sice už nehlásí chybu (alert nevyskočí) a i Firebug hlásí, že je vše OK, ale v databázi se nic neaktualizuje. Nevíte čím to může být? Díky.
Parametry se předají korektně:

do	updateOrder
id	11
order	15,11,3,4
Bernard Williams
Člen | 207
+
0
-

Mrkni, jestli nemáš něco zalogované v /log. Pokud ne, tak zkus dát celý ten blok kódu z toho signálu do tohoto:

try {
		....
} catch (Exception $e) {
    Debugger::log($e->getMessage(), Debugger::ERROR);
    throw $e;
}

Pokud ti to nic nezaloguje, tak máš asi chybu v SQL dotazu – tj. je sice korektní, ale nic v DB nezmění.

Pak bych ještě třeba zkusil spustit celou akci bez AJAXu – zkrátka celou URL předávanou AJAXem dáš do adresního řádku prohlížeče.

Editoval Bernard Williams (18. 7. 2011 21:45)

Ani
Člen | 226
+
0
-

Zalezi jestli mas dobre to MenuModel::updateOrder($value, $i);

Plus mi to nepřijde moc efektivní, přesouvat každej obrázek extra na pořadí?

Bernard Williams
Člen | 207
+
0
-

Ani: Taky bych řekl. Já osobně to uložím do DB až po kliknutí na tlačítko.

Darkry
Člen | 101
+
0
-

Díky moc. Měli jste pravdu, chyba byla v modelu. Už to funguje. Co se týče neefektivnosti je to řazení položek v menu takže se bude jednat max. o 10 položek, tak jsem upřednostnil pohodlí uživatele. Ale samozřejmě při větším množství požadavků by to bylo lepší udělat jak navrhoval Bernard.

piskotek
Člen | 32
+
0
-

ahoj,
poradilo se mi zprovoznit dle tohoto navodu, razeni obrazku…
rozsiril jsem si to o to, ze se to zpracuje az po kliknuti na button…
vse funguje jak by asi melo, data se ulozi do db, ale nasledne se uz neprovede invalidateConrol ani redirect

<script>
	$(function() {
		var output;
		var order = $( "#sortable" ).sortable();
		$( "#sortable" ).disableSelection();
		$("button.ajax").click(function() {

			//console.log(order.sortable( "toArray" ).toString());
			$.get({link 'updateOrder!'}+ "&order=" + order.sortable( "toArray" ).toString());
		});
	});
	</script>
public function handleUpdateOrder( $order) {
	$i = 0;
      foreach (explode (',', $order) as $value) {
          $i++;
	     $this->context->createImages()->where(array('name_obr'=>$value))->update(array('razeni'=>$i));

	}


	if (!$this->isAjax()) {
	$this->flashMessage('Seřazeno ...');
	//$this->invalidateControl('xpokus');
      $this->presenter->redirect(':Admin:Upload:');
  } else {
	$this->invalidateControl('xpokus');

  }
      }

poradite mi nekdo?