Odeslání formuláře s animací

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

Ahoj,
mám formulář pro odesílání komentářů. Formulář odesílám ajaxově a vše funguje. Chtěl bych ale, aby se nový komentář zobrazil s animací slideDown(). Není mi stále úplně jasná práce s nette.ajax.js, možná obecně s javascriptem. Prosím tedy o nakopnutí, díky.

akadlec
Člen | 1326
+
0
-

No tak to potom seš ale na špatném fóru. To co ty chceš (pokud sem tě pochopil dobře) je animace pro zobrazení formuláře a o to se stará JS a né Nette či nette.ajax.js

Musíš si nastudovat něco o jQuery a slide pokud to chceš dělat pomocí něho

Xantes
Člen | 28
+
0
-

Po jQuery vím, co chci. Jde mi spíše o to, že normálně bez nette bych napsal něco jako:

$('#addCommentForm').submit(function(e) {
	e.preventDefault();

	$.post('ajax.php', $(this).serialize(), function(msg) {
		$(msg.comment).insertBefore('#addCommentForm').hide().slideDown();

	...

});

Ale nevím, jak na to za pomocí nette.ajax.js. Samozřejmě mi to ajaxově funguje, ale bez toho efektu. Formulář má jen classu ajax a nic podobného, jako kód výše není, tak nevím, kam dopsat ten efekt.

Může mě někdo nasměrovat?

akadlec
Člen | 1326
+
+1
-

Viz doku od nette.ajax.js

$('#addCommentForm').submit(function(e) {
    e.preventDefault();

    $.nette.ajax({
		url: $(this).prop('action'),
		data: $(this).serialize(),
		success: function(msg) {
	        $(msg.comment).insertBefore('#addCommentForm').hide().slideDown();
		    ...
		}
	});
});
Vojtěch Dobeš
Gold Partner | 1316
+
+2
-

Dokonce se to dá zjednodušit:

$('#addCommentForm').submit(function(e) {
    $(this).netteAjax(e).done(function(msg) {
        $(msg.comment).insertBefore('#addCommentForm').hide().slideDown();
        ...
    });
});

Editoval Vojtěch Dobeš (21. 4. 2015 10:52)

Vojtěch Dobeš
Gold Partner | 1316
+
+1
-

A uděláš dobře, když na ten formulář CSS třídu ajax nedáš, právě poněvadž si jeho odeslání obsluhuješ a ajaxuješ po svém.

one-two
Člen | 80
+
+2
-

Vojtěch Dobeš napsal(a):

Dokonce se to dá zjednodušit:

$('#addCommentForm').submit(function(e) {
    $(this).netteAjax(e).done(function(msg) {
        $(msg.comment).insertBefore('#addCommentForm').hide().slideDown();
        ...
    });
});

nechceš hodit tohle do dokumentace na github? zrovna nedávno sem to řešil a poměrně dlouho sem se s tim patlal, než sem přišel na to, že to stačí takhle jednoduše :)

Vojtěch Dobeš
Gold Partner | 1316
+
+1
-

Nechceš připravit PR :) ?

Čamo
Člen | 798
+
0
-

Ja akurát presne toto riešim a tiež som to na githube márne hľadal.

Xantes
Člen | 28
+
0
-

Děkuji oběma. Stále mi však něco uniká.
V presenteru mám po odeslání formu něco takového:

if ($this->isAjax()) {
	$this->redrawControl('comments');
} else {
	$this->redirect('this');
}

v šabloně:

{snippet comments}
{foreach $comments as $comment}
	...
{/foreach}
{/snippet}

a js nyní tedy:

	$('#addCommentForm').on('submit', function(e) {
		e.preventDefault();

		$.nette.ajax({
			url: $(this).prop('action'),
			data: $(this).serialize(),
			success: function(msg) { // jak tady do msg dostanu ten komentář?
				console.log(msg.comment);
				$(msg.comment).insertBefore('#addCommentForm').hide().slideDown();
			}
		});
	})

Ptám se asi hloupě, ale v javascriptu jsem začátečník a do teď jsem ajax v nette používat tak, že jsem přidal class=„ajax“ a fungovalo to. Bez nette jsem to měl vyřešeno, ale s ním si nevím rady.
Navíc, i kdyby se mi podařilo komentář dostat a zanimovat, jak chci, tak už je stejně pozdě, protože redrawControl(‚comments‘) už to překreslil, ne?

Mohl by mi to někdo objasnit?

akadlec
Člen | 1326
+
0
-

A dosáhnout chceš tedy čeho? Pokud nějakou animaci toho co překreslíš tak si to ještě obal dalším kontejnerem (DIVem apod.) a tu animaci dej na něj.

Vojtěch Dobeš
Gold Partner | 1316
+
+2
-
  1. První argument callbacku v property success (anebo callbacku předaného do done metody, což je modernější a doporučovaný způsob) je body, které přišlo ze serveru. Pokud to je JSON, tak je to rovnou javascriptový objekt. Říkejme mu pro jednotnost termínů payload.
  2. Metoda redrawControl vyvolá překreslení daného snippetu, ale to neznamená, že by něco provedla v prohlížeči. Jediné, co zajistí, je, že v objektu payload bude objekt snippets, kde pod klíčem (který generuje Nette a bude se rovnat přibližně stringu snippet--comments) najdeš HTML toho překresleného snippetu.
  3. nette.ajax.js má defaultně zapnutou extenzi, která se příznačně jmenuje snippets. Ta se dívá do payload.snippets, celé to prosviští foreachem, podle klíčů najde odpovídající elementy snippetů (každý snippet má to snippet--comments aj. jako HTML atribut id) a jejich obsah nahradí tím novým HTML.

Pokud dobře chápu tvůj záměr, snažíš se Ajaxem načítat nové komentáře a chceš, aby se ty nové přidaly k již existujícím a objevily se slide animací.

Jak na to? Udělal bych to takto. Zaprvé, po přidání komentáře si do šablony do pole $comments dej jen ten nový komentář, jinak následující kód nebude fungovat.

<div n:snippet="comments" data-ajax-snippet-behavior="prependAndSlide"> {* dám si na element snippetu svůj custom data atribut *}
{foreach $comments as $comment}
	<div class="comment">
		...
	</div>
{/foreach}
</div>
var snippetsExtension = $.nette.ext('snippets'); // vytáhnu si extenzi pro její nakonfigurování
var originalApplySnippet = snippetsExtension.applySnippet;
snippetsExtension.applySnippet = function ($el, html, back) {
	var behavior = $el.date('ajax-snippet-behavior');
	if (behavior && this.behaviors[behavior]) {
		this.behaviors[behavior]($el, html, back);
	} else {
		originalApplySnippet($el, html, back);
	}
};
snippetsExtension.behaviors = {};
snippetsExtension.behaviors['prependAndSlide'] = function ($el, html, back) {
	var $comment = $(html);
	$comment.hide();
	$el.prepend($comment);
	$comment.slideDown();
};
Xantes
Člen | 28
+
0
-

@VojtěchDobeš díky za objasnění, i když je na mě ten js kód trochu složitý.

Nakonec jsem to vyřešil tak, že jsem $this->redrawControl(‚comments‘) vůbec nepoužil, místo toho jsem si ten komentář poslal přes $this->payload->comment a odchytil jsem si ho v tom callbacku success property. Takže výše můj js zdroják jsem jen minimálně upravil a fungovalo to, akorát jsem narazil, že jsem v poslaném komentáři potřeboval latte, tak jsem nakonec místo payload, odeslal šablonu

if ($this->isAjax()) {
	$this->template->setFile('comment.latte');

akorát nevím, zda je to správné, čisté řešení?

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Myslím že na tom principielně není nic špatného.