Po ajaxe sa spustia všetky extensions
- iNviNho
- Člen | 352
Mám pár buttonov na stránke, ktoré sú robené cez Ajax. Fungujú správne, ale asi som žil doteraz v omyle, že po odoslaní akéhokoľvek ajaxu sa mi spustia všetk .ext()
Napríklad mám 2 extensiony
$.nette.ext("delete", {
complete: function () {
$("#cboxClose").click();
}
});
$.nette.ext("objednavkadone", {
success: function () {
console.log("objednavka done");
}
});
V šablone mám colorbox a ked kliknem na zatvoriť, tak sa spustí $(„#cboxClose“).click(), ale v consoli vidím aj console.log(„objednavka done“). Niekde mi niečo uchádza?
<a n:href="zmazKategoriu!, $k->id_kat" name="delete" class="ajax">
Ďakujem.
Editoval iNviNho (29. 1. 2014 21:42)
- Majkl578
- Moderator | 1364
Při spuštění ajaxového requestu se spustí všechny registrovaná rozšíření a všechny jejich příslušné stavové callbacky. Výjimku tvoří explicitně vypnutá rozšíření přes off resp. data-ajax-off.
Pokud chceš při kliku na nějaký odkaz provést něco specifického, obsluhuj ho explicitně, ne třídou class, ale ručním nabindováním na click a voláním $.nette.ajax.
- Jiří Nápravník
- Člen | 710
Protože ty callbacky co tam jsou jsou globální, jinak bys nemohl udělat něco jako spinner, který bude po každém ajaxu apod. A halvně musí se spustit všechny, po každém requestu, protože můžeš mít v jiné extensioně funkcionalitu, která je nezbytná pro tuhle.
Ty pokdu te dobre chapu, tady delas to, že děláš jako extension jendoduchý úkon, jako kliknu na odkaz a tohle se udělá, kliknu na jiný odkaz a to je jiná extension. Lepší je udělat si extension pro obejednavky napriklad. A tam v callbacku load: si nabinduješ přímo odkazy, třeba takto:
(function($) {
$.nette.ext(
{
load: function() {
$('.articleDiscussion .smiles a').off('off', this.smileClick).on('click', this.smileClick);
}
},
{
smileClick: function(e) {
e.preventDefault();
var code = $(this).attr('title');
var textarea = $(this).closest('form').find('textarea');
textarea.val(textarea.val() + code + ' ');
}
}
);
})(jQuery);
Tím, že se ti ta extensiona spustí po každém výsledku ajaxu, tak máš i zajištěno, že se rovnou nabinduje to co je třeba.
Ty complete, sucess apod. ty se používají jen pro globální kontext. Pokud bys to ale vyloženě nutně potřeboval, žeší se to tak, že se pošle v payloadu nějaký identifikátor, a ty si pak zkontroluješ, ež tam je, pokud není, tak vyskočíš.
- iNviNho
- Člen | 352
No to nejako nedáva zmysel … Ja som to tak správne pochopil, že extensiona sa zavola vtedy ked ju potrebujem . Však načo sa bude zbytočne spúšťať napr. 10 exts ked potrebujem spustiť metody iba pre danu extension.
Načo je tam pri $.nette.ext(„delete“, {}); to slovo delete?
No nič ak je to takto spravené, tak vyskúšam zajtra ako to teda funguje …
- David Matějka
- Moderator | 6445
nazev extension je identifikator, abys ho mohl vypnout, nakonfigurovat nebo aby na nem bylo nejake jine extension zavisle, viz doc
- Jiří Nápravník
- Člen | 710
matej21 tak mě na druhou stranu napadá. Není možné nějak udělat to, aby byla extensiona spíše defaultně vypnutá a já ji zapl, až na pokyn? Konkrétně o co jde (a pravděpodobně to řeší i iNviNho). Mám takhle několik extensions – pro články, pro fotogalerii atd. No a když jsem na článku, tak je pro mě třeba v podstatě jen tu extension pro články a ostatní mě neazajímají, ideální by bylo, aby se ani neinicializovali, prostě jako by ta extensiona nebyla. Protože pak se mi při každíém requestu leze zybtečně do těch ostatních extensions a je to pomalejší.
Jde to udělat tím, že si přidám jen ty extensiony na stránku co potřebuji, ale to nejde, mám všechyn js v jednom souboru.
Pak je řešením, rozhdoovat podle DOMu, když tam budu mít nějaký např. idčko, tak ať se definuje ta extension, ale to není úplně pěkné. Je nějaké lepší řešení?
- honos
- Člen | 109
Jiří Nápravník napsal(a):
matej21 tak mě na druhou stranu napadá. Není možné nějak udělat to, aby byla extensiona spíše defaultně vypnutá a já ji zapl, až na pokyn? …
mozna pomoci atributu data-extension-on=‚name‘ nasledne nejaky scriptik
v js ktery projde ty parametry z atributu a provede
zapnuti $.nette.ext('name', 'functionname');
Editoval honos (30. 1. 2014 0:39)
- Vojtěch Dobeš
- Gold Partner | 1316
Vzhledem k tomu, že všechen JS by měl být na produkci v jednom souboru a minifikovaný, nemá podle mě smysl řešit to podmíněným načítáním souborů. V tom případě mi rozhodování podle DOMu přijde zcela ok. Případně si lze udělat jednoduše vlastní API pro defaultně vypnuté extenze:
prepare
může upravit settings
, a díky tomu
ovlivnit, jaké extenze budou povolené.
function addConditionalExtension(name, events, context) {
$.nette.ext(name, $.extend(events, {
prepare: function (settings) {
if (!settings.nette || !settings.nette.el.is('[date-' + name + ']') {
if (!settings.off) {
settings.off = [];
}
settings.off.push(name);
}
}
}, context);
}
Pomocí nové funkce provedeme registraci extenze:
addConditionalExtension('my-ext', {
success: function () { ...
});
Odkazy, pro které se má použít extenze my-ext
, musí mít
datový atribut [data-my-ext]
:
<a class="ajax" data-my-ext>
Editoval vojtech.dobes (30. 1. 2014 11:20)
- akadlec
- Člen | 1326
Na toto jsem narážel už dříve. Ono by možná nebylo od věci udělat něco jako „autowired“ že by se v defaultu ty extension připojovaly automaticky a pokud by se jim přidat příznak autowired=off tak by se nespouštěly automaticky ale jen v případě že by se uvedly např v data-ajax-on=„{ext1, ext2,…}“ co vy na to?
@vojtech.dobes: tvé řešení ale počítá s tím že musíš tu aditional funkci někde volat ne? Takže si musíš sestavit nějaké if-else kde provedeš přiřazení daný ext ne?
Editoval akadlec (30. 1. 2014 9:53)
- Vojtěch Dobeš
- Gold Partner | 1316
@akadlec Ne, ta additional funkce se bude volat
stejně jako $.nette.ext
. V tom je ta pointa, že je defaultně
vypnutá, a zapnout ji lze tím datovým atributem.
- iNviNho
- Člen | 352
Podľa doc som narazil na fungujúce riešenie.
<?php
data-ajax-off="názov-extensions"
?>
Riešil som to kvôli tomu, lebo mám na jednej šablone pridavanie produktov do koša pomocou ajaxu a následne aj vytvorenie objednávky pomocou ajaxu. A po pridaní produktu do koša sa, ako sme riešili, spustili všetky extensions a tým pádom mi po každom pridaní vyskakovalo okno, že objednávka bola vytvorená.
demo http://www.ekotrim.sk/…dalny-listok
Takže riešenie:
<?php
$.nette.ext("delete", {
complete: function () {
$("#cboxClose").click();
}
});
$.nette.ext("objednavkadone", {
success: function () {
$(".inline").click();
// vyvolávam $(this).colorbox({inline:true, width:"50%", open: true});
}
});
?>
a v šablone
<?php
{input odoslat class => "ajax", data-ajax-off => "delete"} // vytvorenie objednávky, ak nevypnem delete, tak by sa colorbox hned aj zatvoril
{input odoslat class => "vlozdokosa ajax", data-ajax-off => "delete objednavkadone"} // vloženie do koša nech nespúšta moje extensiony
?>
Ešte som to musel pridať aj na button, ktorý maže produkty z košíka, ten je taktiež ajaxovo riešený.
Možno pre môj prípad by bolo najlepšie, ak by sa spúštali defaultne extensions ako snippets, redirect, abort atd. Následne mnou definované extensions by som spúšťal napr.:
<?php
data-ajax-on="názov_extensionu"
?>
Teraz je to ešte v pohode, ale problém nastane až ked budem mať viac extensions …
- Vojtěch Dobeš
- Gold Partner | 1316
@iNviNho Ehm, četl jsi můj příspěvek? Mezi uživatelsky definovanými a defaultními extensions není žádný rozdíl, a ani ho neplánuji – žádné defaultně vypnuté extenze nebudou. Ale není problém si naimplementovat, aby se tak vlastní extenze chovaly.
- Vojtěch Dobeš
- Gold Partner | 1316
V pohodě, mě nic neurazilo :), jen se snažím ukázat, že
nette.ajax.js
žádné defaultně vypnuté extenze explicitně
podporovat nemusí, protože extenzi samotnou lze naimplementovat tak, aby se
tak chovala.
- akadlec
- Člen | 1326
@iNviNho: tvá cesta je imho špatná, ty data-ajax-off atributy teď budeš muset dávat všude kde je nechceš použít a pokud máš zajaxovaných více prvků stránky tak se z toho zblázníš. Ve tvém případě bys to měl řešit tak jak psal vojtěch
@vojtech.dobes: jop máš pravdu přehlédl jsem tu podmínku která je navazuje v té funkci. V tom případě by to šlo udělat cca tak jak jsem navrhoval ne? Udělat si data-ajax-on a v něm vypsat ext co se mají spustit které by zároveň byly definovány v té podmínce a pokud by vyhovovaly tak by fungovaly jinak ne. co?
- Jiří Nápravník
- Člen | 710
@vojtech.dobes díky za návrh řešení, vůbec jsem nějak nezaregistroval, že je tam i callback na prepare.
To s tím atributem data-ajax-on, pro mě úplně ideální není protože to budu msuet zase dávat ke všem odkazům, co chci zajaxovat. Pro mě je spíše lepší dát nějakou classu, id obalujícímu divu a podle toho pak rozhodnout, že tuhle extension použiju.
Jak ten prepare funguje, kdy se volá? Nešlo by v něm udělat, právě rozhodnutí podle domu, jestli mám v domu to id,class tak to povolit jinak zakázat.
Ted to řeším tak, že mám v load, success apod. podmínku
if ($('.article').length === 0) {
return;
}
aby se zybtečně neprocházeli ty callbacky co tam mám apod. Neřeší tohle prepare? Init ten to taky asi neřeší co? Ten je jen při prvním načtení. Jde mi prostě o to, aby když nemám v DOMu ty požadované prvky, tak aby se to ideálně tyhle callbacky přeskákalo ani neinicializovalo
- Vojtěch Dobeš
- Gold Partner | 1316
V load
je naprosto korektní, pokud to chceš rozhodovat
globálně. Událost prepare
bohužel chybí v dokumentaci
(omlouvám se), a volá se ještě před before
(která může
vrácením false
zrušit ajaxifikaci). Hodí se tedy na
„přípravu“ requestu. Předává se jí pouze objekt
settings
.
Na každý usecase se hodí trochu jiný přístup :). prepare
se hodí v případě, že je třeba spuštění extenzí rozhodovat na
úrovní jednotlivých odkazů/tlačítek/formulářů…
- Jiří Nápravník
- Člen | 710
vojtech.dobes napsal(a):
V
load
je naprosto korektní, pokud to chceš rozhodovat globálně.
či-li když udám tuhle podmínku v load, tak už ji nemusím udávat v success? To mi nějak nefunguje, musím tu podmínku pak rozkopírovat i do success, complete apod. aby se kdyžtak přeskočila.
- Jiří Nápravník
- Člen | 710
Jde mi o klasický případ, kdy potřebuji mít extension, která se mi stará například o články. Tam pak potřebuji nabindovat nějaký věci apod. (v load). A pak taky potřebuji pokud proběhl ajaxový poadavek správně, tak něco vykonat.
No a vzhledem k tomu, že extensiony jsou globální, tak pokud nechci aby se zbytečně procházel load: a success: apod. i když tu extensionu nepotřebuju vůbec, tak dávám na začátek těch callbacku, kontrolu zda je v DOMu nějaká třída, co potřebuji.
A otázka zní, jde to udělat nějak jednodušeji, než to kopírovat do každého callbacku? Bylo by ideální mít tam nějaký callback, který se bude volat jako první a v případě, že podmínka kterou si dám nebude splněna. Tak se vůbec nebude dalšími callbacky zabývat, nebudu to tak muset řešit v každém callbacku solove
Tady je kod jak to dělám ted:
{
load: function() {
if ($('.article-edit').length === 0) {
return;
}
//jsem v článku řeším ty věci co potřebuji
},
success: function(payload) {
if ($('#article-edit').length === 0) {
return true;
}
}