Jak na extension a znovunabindování AJAXu?

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

Zdravím,

mám takovej menší problém s ajaxovým zpracováním. Mám formulář, který odesílám ajaxem. Bohužel po prvním překreslení se mi neprovedlo navázání ajaxu na prvky a další požadavek teda proběhl klasicky bez ajaxu.

Proto jsem po hedání na foru vytvořil takové pofidérní bindování:

$(document).ready(function(){
	$("#frm-projectUsersForm.ajax").live("click", function (e) {
		$.nette.ajax(this.href, this, e);
		return false;
	});
});

U tohoto byl problém v tom, že mi po překreslení přestalo úplně fungovat jQuery.

Zkoušel sem hledat dál a několikrát sem si zkoušel pohrát i s extensionama z knihovny nette.ajax.js , kterou používám, ale vždycky bez nějakýho výsledku. Nechápu co dělám špatně, ale ani jedna extensiona mi nefunguje, i když tam mám jen obyčejnej alert(). Takhle to vypadá v mém kódu:

<script src="{$basePath}/js/jquery.js"></script>
<script src="{$basePath}/js/netteForms.js"></script>

<!-- Core Javascript - via CDN -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js"></script>
<script type="text/javascript" src="{$basePath}/js/main.js"></script>
<script type="text/javascript" src="{$basePath}/js/custom.js"></script>
<script type="text/javascript">
	$(function () {
		Core.init();
		$.nette.init();
		$.nette.ext({
			complete: function (payload) {
				$.nette.load();
				alert('snippet complete');
			},{
				alert('blabla');
			}
		});

	});
</script>

Bohužel ale v tomto druhém případě nefunguje AJAX vůbec. Ajaxové zpracování se kompletně vypne.

Dokázal by mi prosím někdo pomoct a poradit, jak to mám správně vyřešit? Budu vděčný za jakoukoliv pomoc, díky.

Zax
Člen | 370
+
0
-

$.live() je v aktuální verzi jQuery deprecated, použij $.on()

Ajaxové extension dej před $.nette.init(); (nejdřív zaregistruj rozšíření a až pak to všechno inicializuj ;-)

Chybí ti první parametr – název rozšíření. Nevím jestli je to přímo povinné, ale třeba to pomůže… např.:

$(document).ready(function() {
    $.nette.ext('consoleLog', {
        success: function(payload) {
            console.log('Incoming payload!');
            console.log(payload);
        },
        error: function(jqXHR, status, error) {
            console.log('Ajax failed!');
            console.log(error);
            console.log(jqXHR);
        }
    );

    $.nette.init();
});

(EDIT: nějak divně se to zbarvuje, asi tam mám syntax error někde, no hledat to nebudu :D )

Editoval Zax (11. 7. 2014 19:51)

serten
Člen | 55
+
0
-

Super, díky moc :-) Tvá odpověď mě nasměrovala ke správnýmu řešení. Je ale teda zvláštní, že když místo .live() použiju .on() tak mi to vůbec nefunguje. Ale s .live() je vše jak má být.
A ta chyba která se ti nechtěla hledat byla jen v poslední složené závorce, která chyběla :-D

Tak ještě jednou díky ;-)

Pavel Macháň
Člen | 282
+
0
-

serten napsal(a):

Super, díky moc :-) Tvá odpověď mě nasměrovala ke správnýmu řešení. Je ale teda zvláštní, že když místo .live() použiju .on() tak mi to vůbec nefunguje. Ale s .live() je vše jak má být.
A ta chyba která se ti nechtěla hledat byla jen v poslední složené závorce, která chyběla :-D

Tak ještě jednou díky ;-)

.live bych nepoužíval, od 1.9 je deprecated

David Kudera
Člen | 455
+
0
-

Od 1.9 je dokonce pryč úplně, alespoň podle dokumentace. Mimochodem je v ní i ukázka, jak přejít správně na on.

Pavel Macháň
Člen | 282
+
0
-

David Kudera napsal(a):

Od 1.9 je dokonce pryč úplně, alespoň podle dokumentace. Mimochodem je v ní i ukázka, jak přejít správně na on.

@DavidKudera Teď na tu dokumentaci koukám a fakt že odstraněno. Takže nechápu jak mu může jít .live na 1.10 viz import jska co tam @serten má.

David Kudera
Člen | 455
+
0
-

No asi to má nějak „pošahané“, protože koukám, že jquery načítá 2×, což je mimochodem chyba.. Jednou od sebe a jednou z cdn. A v cdn ta funkce nikde není

serten
Člen | 55
+
0
-

Díky za upozornění, toho jsem si právě vůbec nevšiml. Ale právě jakmile nechám načítání pouze z CDN, tak mi to po předělání na .on() nefunguje. Moje konečná verze je:

$(document).ready(function(){
	$( "#frm-reqInfoForm.ajax" ).on("click", function (e) {
		$.nette.ajax(this.href, this, e);
		return false;
	});
});

protože to ještě vlastně pokaždé překresluju v snippetu. Ale bohužel to nefunguje jak má. Jenou se ten požadavek provede a podruhé už to není nabindovaný a provede se klasické přesměrování. Nevíte kde by mohla být chyba?

David Kudera
Člen | 455
+
0
-

zkus to změnit na:

$(document).on('click', '#frm-reqInfoForm.ajax', function(e) {
	e.preventDefault();
	$.nette.ajax(this.href, this, e);
});

kdyžtak na id vygenerovaná frameworkem by se spoléhat takhle v kódu určitě nemělo. A místo return false by se mělo používat raději e.preventDefault();

Edit: každopádně načítání dvou různých verzí je chyba a mělo by se to vyřešit ;-)

Editoval David Kudera (16. 7. 2014 12:04)

akadlec
Člen | 1326
+
0
-

máš aktuální verze jquery?

serten
Člen | 55
+
0
-

Tak verze sem samozřejmě promazal a na základě dotazu akadlece sem zvýšil verzi jQeury na nejaktuálnější 1.11.1. Ještě jsem zkusil druhý kód pro nabindování, co mi poradil David Kudera a zkusil jsem změnit selector na form.ajax, ale nic z toho nefunguje. Vyhodil jsem to nakonec i ze snippetu, aby se to pořád nepřekreslovalo.

Zajímavé ale je, že mám na stejné stránce ještě ajaxově zpracované komentáře, ale po prvním překreslení prvního formuláře ajaxové zpracování u komentářů dál funguje.

Nenapadá Vás čím by to mohlo být? Rád poskytnu další informace.

Díky

David Kudera
Člen | 455
+
+1
-

zkus to ještě takhle:

$(document).on('click', 'form.ajax', function(e) {
    e.preventDefault();
    $.nette.ajax(this.href, this, e);
});

jo moment… to frm-reqInfoForm id je id formuláře ne?? Jestli jo, tak opravdu na něj chceš navěsit click událost? Nemělo by to být navěšené na submit toho formuláře?

$(document).on('click', 'form.ajax input[type="submit"]', function(e) {
    e.preventDefault();
    $.nette.ajax(this.href, this, e);
});

tohle se aplikuje na všechny submity ve formulářích s třídou .ajax

Edit: a nebo událost submit (místo click) přímo na tom formu

Editoval David Kudera (16. 7. 2014 15:59)

akadlec
Člen | 1326
+
0
-

a nemáš tam třeba na více míste voláno spuštění ajaxifikace? Případně nějaké duplicity? Protože pokud používáš nette.ajax.js tak ten si to bindování řeší sám a sám se dynamicky zavěsí na existující i budoucí elementy pokud je u nich třída ajax

serten
Člen | 55
+
0
-

Je to celé nějaké zvláštní, všude jinde ajaxové zpracování funguje v pohodě, jen v tomto jednom případě ne. Právě že jsem nidke jinde toto bindování nemusel řešit, vše se nabindovalo znova samo. Když jsem použil všechny rady, které jste mi tu napsali, tak se mi vždy provedl první ajaxový požadavek, ale neprovedla se mi žádná akce v extension, což vypadá, jako by už s tím samotným ajaxovým zpracováním nebylo něco v pořádku. Zkoušel jsem otestovat, jestli mi to dělalo i u toho .live() a ono ne, tam všechno funguje jak má.

Mám někam nahodit zdrojové kódy presenteru a šablony, aby ste se na to mohli podívat líp?

akadlec
Člen | 1326
+
0
-

tak pokud ti funguje .live() máš imho špatnou verzi jquery když tato metoda byla deprecated a už je tuším i removed.

serten
Člen | 55
+
0
-

Je to celé zvláštní, ale mám tam nahozenou pouze jednu a to nejnovější verzi jQuery. Tohle jsou jediné skripty, které tam vkládám. A zkoušel jsem to různě prohledávat, ale nic navíc jsem nenašel, pokud bych se náhodou přehlídl a dal to tam dvakrát.

<script src="/js/netteForms.js"></script>

<!-- Core Javascript - via CDN -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.0/jquery-ui.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js"></script>
<!-- Plugins - Via CDN --
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
<!--<script type="text/javascript" src="vendor/plugins/datatables/jquery.dataTables.min.js"></script> Local Option -->

<!-- Plugins -->
<script type="text/javascript" src="/vendor/editors/xeditable/js/bootstrap-editable.js"></script>
<script type="text/javascript" src="/vendor/plugins/chosen/chosen.jquery.min.js"></script>
<script type="text/javascript" src="/vendor/plugins/gritter/js/jquery.gritter.min.js"></script>

<script type="text/javascript" src="/js/uniform.min.js"></script>
<script type="text/javascript" src="/js/main.js"></script>
<script type="text/javascript" src="/js/custom.js"></script>

<script src="/js/nette.ajax.js"></script>
David Kudera
Člen | 455
+
0
-

No ale kde se ti tam teda jen tak bere to live? Schválně si takhle otevři neminifikovanou verzi jquery 1.11.1 a zkus si tam vyhledat přímo slovo „live“. Třeba to totiž způsobuje ten tvůj problém..

Editoval David Kudera (17. 7. 2014 12:02)

akadlec
Člen | 1326
+
0
-

v té minifikované verzi .live() není. Podívej se na http přenos při načítání stránky jestli si třeba nějaký skript ještě sám neincluduje jinou verzi jquery a pak by ti to mohlo dělat bordel.

serten
Člen | 55
+
0
-

Tak to vážně netuším, kde se bere. jak mi poradil akadlec, tak sem projel http přenos, otevřel sem si všechny js soubory, které to natahuje a vyhledával v nich live a prostě nic. CHová se to nějak divně. Je pravda že jednu chvíli se mi v konzoli zobrazovalo že .live() je deprecated, ale to bylo jen v jednom případě a teď se k té chybě zase nemůžu dohrabat.

David Kudera
Člen | 455
+
0
-

Asi nemáš nějakou veřejně přístupnou verzi že?

akadlec
Člen | 1326
+
0
-

a v tom http přenosu bylo tedy jen jedeno načtení jquery?

serten
Člen | 55
+
0
-

Veřejně dostupnou verzi bohužel nemám, protože se jedná o firemní projekt. Ale mohl bych dát k dispozici layout šablonu a presenter a šablonu stránky, které se to týká, jeslti by to pomohlo, co vy na to?
akadlec toho co sem to projížděl tak ano, jen jedno a to bylo z toho CDN

David Kudera
Člen | 455
+
0
-

Stačily by zatím klidně jen ty šablony jak píšeš a taky js soubor, kde tohle řešíš

Editoval David Kudera (21. 7. 2014 11:13)

serten
Člen | 55
+
0
-

Tak tady je odkaz na archiv s šablonami: http://uloz.to/…/sablony-zip
V otmto případě teda nemám JS kód oddělený v samostatných souborech. Je v samostatných blocích na konci souboru, v případě layout šablony jsou inicializační na konci HEAD tagu.

David Kudera
Člen | 455
+
0
-

No.. tak nějak tak nechápu, proč máš js zabalený ve snippetech.. Snippety by měli být útržky html bloků a určitě ne js kód

Editoval David Kudera (21. 7. 2014 12:21)

serten
Člen | 55
+
0
-

Když se provede ten ajaxovej požadavek a překreslí kus stránky, tak aby se znovunabindovali jednotlivé skripty znovu na ty položky. V některých částech mi ty skripty po překreslení nefungovaly, tak jsem to vyřešil tímto způsobem.

David Kudera
Člen | 455
+
0
-

Zkus tohle: link. Na začátku se provede to js a v alertu bude „snippet code called“, po 1s se to js jen tak překreslí a zobrazí hlášku „snippet code changed“. První hláška „snippet code called“ už se ale znovu nezavolá. Překreslený js kód se totiž takhle znovu sám nevolá

Editoval David Kudera (21. 7. 2014 13:48)

serten
Člen | 55
+
0
-

Jasný, chápu, takže to překreslování jak to mám já nemá smysl. Ale jakým způsobem tedy znovunavázat skripty? Protože se mi i na jiném místě stává, že když překreslím snippet, tak mi pak nefungují některé jQuery skripty.

David Kudera
Člen | 455
+
+1
-

Ano to se děje třeba když se události nabindují přímo na element.

$('input[type="submit"]').click(function() {
	doSomething();
});

takhle je ta událost přidána přímo na ten daný prvek, když se ale překreslí (je úplně jedno jak), tak se ten předchozí vlastně smaže a vytvoří se nový prvek, který na sobě tyto události nemá.

Dřív se na to používalo live

$('input[type="submit"]').live('click', function() {
	doSomething();
});

a nyní se používá jen on

$(document).on('click', 'input[type="submit"]', function() {
	doSomething();
});

a to vlastně navěsí událost na celý document, ale vyfiltruje ji vždy znovu pro daný prvek, takže překreslení nevadí.

Jak už tu ale někdo psal, v základu si tohle dělá nette.ajax sám.

Editoval David Kudera (21. 7. 2014 16:20)

serten
Člen | 55
+
+1
-

Díky všem za pomoc a rady, hlavně tobě David Kudera. Díky vašim radám sem si konečně vědomil jak se to má správně dělat a vyčistil jsem si šablony od špatně fungujícího kódu a už vše funguje jak má :-) Ten JS kód ve snippetech byl vážně zlo :-D

Ještě jednou velké díky ;-)

David Kudera
Člen | 455
+
0
-

Dalším krokem může být vyčlenění js ze šablon do samostatných .js souborů. Teď už to budeš moct udělat, když to není ve snippetech a nejsi tím omezován. Tak si to zpřehledníš ještě víc ;-)