nette.ajax.js – alt. obsluha pro AJAX s jQuery
- Jan Mikeš
- Člen | 771
@iguana007 zrus uplne ten js co jsi psal vyse (to zaveseni) a pouzij ten update co jsem ti psal ja. Tvuj kod by funguval pouze v pripade, ze neprekreslujes #switchesBlock
Uplne smaz
<script>
$(function(){
$.nette.load();
$('#switchesBlock').on('click', '.ajax', function(e){
(event.preventDefault) ? event.preventDefault() : event.returnValue = false;
$.nette.ajax(this.href, this, e);
});
});
</script>
A primo v nette.ajax.js zkus nahradit
<script>
$(this.linkSelector).off('click.nette', rh).on('click.nette', rh);
</script>
Nahrad za
<script>
$("body").off('click.nette', this.linkSelector, rh).on('click.nette', this.linkSelector, rh);
</script>
- akadlec
- Člen | 1326
imho $.nette.load(); je v tom snippetu naprosto zbytečné. A místo .on eventu může použít obyčejný .click event protože ten element na které ten JS naslouchá stejnak po requestu přepíšeš. Nicméně pokud ti to jede ve FF a chrome tak se v IE podívej do té konzole, třeba ti tam někde vypadl nějaký středník apod. na co je IE citlivé.
- Jan Mikeš
- Člen | 771
Atribut data-ajax-off nefunguje na formuláře (extension se normálně
volá).
Pokud zkouším odkaz na stejnou url s attributem data-ajax-off, extension je
pro tento request vypnutá.
Existuje pro to nějaký easy workaround, nebo se jedná o bug?
Takto vypadá výsledné html v DOMu:
<form action="/strojovy-park/company/send-demand/240?companyVehicleId=97" method="post" class="ajax" data-ajax-off="map" id="frm-demandForm-form" novalidate="">
- Vojtěch Dobeš
- Gold Partner | 1316
Lexi napsal(a):
Atribut data-ajax-off nefunguje na formuláře (extension se normálně volá).
Pokud zkouším odkaz na stejnou url s attributem data-ajax-off, extension je pro tento request vypnutá.
Existuje pro to nějaký easy workaround, nebo se jedná o bug?Takto vypadá výsledné html v DOMu:
<form action="/strojovy-park/company/send-demand/240?companyVehicleId=97" method="post" class="ajax" data-ajax-off="map" id="frm-demandForm-form" novalidate="">
Nemáš třídu ajax
i na tlačítku toho formuláře?
- Jan Mikeš
- Člen | 771
@vojtech.dobes nemam, vyresil jsem to workaroundem, ze do extension MAP, kterou potrebuji pro tento formular vypnout, jsem pridal check, kterym elementem je ajax odesilan (existuje nejake jine snadne reseni, jak navazat extension pouze na jeden konkretni ajax call?). kazdopadne asi to neni uplne nejlepsi reseni, ale funguje
Mozna bude zakopan pes v tom, ze i sam formular je loadovan ajaxem do popup okna, ale nevim… o vikendu budu mit vice casu, tak bych mohl vse otestovat, najit chybu a pripadne vytvorit issue/pull request.
- akadlec
- Člen | 1326
Hele pokud chceš ext navázat jen na něco, tak tady o několik stránek dříve jsem to řešil a je tam i návrh od vojty jak na to. Já jsem si pro tohle udělal atribut data-ajax-on co mě ty ext co byly podmíněné zapínal:
function addConditionalExtension(name, events, context) {
$.nette.ext(name, $.extend(events, {
prepare: function (settings) {
if (settings.nette) {
var ajaxOn = settings.nette.el.data('ajax-on');
if ( !settings.nette || !ajaxOn instanceof Array || $.inArray(name, ajaxOn) < 0 ) {
if ( !settings.off ) {
settings.off = [];
}
settings.off.push(name);
}
}
}
}), context)
}
a pak jednotlivé ext jsem přidával takto:
addConditionalExtension('avatarUpload', {
init: function() {
// Init image area select
this.initialize($('body'));
},
success: function (payload, status, xhr, settings) {
var snippetsExtension = this.ext('snippets');
// Some snippets were returned...
if ( payload.snippets ) {
// ...go through all snippets
for ( var id in payload.snippets ) {
var $el = snippetsExtension.getElement(id);
// Check if snippet element exists
if ( $el.exists() ) {
// Init image area select
this.initialize($el);
}
}
}
}
});
- gliny
- Člen | 25
Ahoj,
docela mě překvapilo, že tento kód
google.maps.event.addListener(marker, 'click', function() {
$.nette.ajax({ url: marker.url }, this, null);
});
mi nezměnil URL a tímpádem nefungovalo tlačítko zpět.
Verze Nette 2.0.16, verze nette ajax 2.0, v bootstrapu správně přidaná history a naincludované nette.ajax.js, history.ajax.js a další js.
//tak jsem to vyřešil tak, že jsem za nette.ajax přidal pushstate, díky tomu se url změní a tlačítko zpět funguje, jen mi nejde do hlavy, že samotný nette.ajax nedělá pushstate? Divné.
history.pushState({}, '', marker.url );
Je už nějaké řešení na to když z ajax požadavku přejdu na neajax a potom použiju tlačítko zpět a zobrazí se vypsaný jen ten poslední snippet? Nepotřebuju mít vždy vše ajaxově ale díky tomuhle je to překážka.
Editoval gliny (15. 2. 2015 15:51)
- Vojtěch Dobeš
- Gold Partner | 1316
Lexi napsal(a):
@vojtech.dobes je nejaka sance, ze se toto rozsireni (data-ajax-on) dostane do oficialniho repozitare?
Koncept defaultně vypnutých extension jsem ještě vnitřně nezpracoval, takže zatím nedokážu říct.
- radas
- Člen | 224
Ahoj, prošel jsem celé toto vlákno a není mi jasná jedna věc. Mám na stránce dva formuláře, které chci odesílat AJAXem, mají tedy class=„ajax“. Jak ale docílím toho, aby se na každém z nich vykonala vlastní sada událostí success, error, complete?
Tento kód se mi volá na obou formulářích. Potřebuji, aby se vykonal jen na jednom a jiný kód na druhém.
$.nette.ext('add_group',
{
success: function(payload, status, jqXHR, settings)
{
if (payload.result == 'ok')
{
$.each(payload.data, function(i, item)
{
if ($.inArray(item.org_id, existingOrgIds) === -1)
{
existingOrgIds.push(item.org_id);
addOrganization(item.org_id, item.name, item.district);
}
});
$('#selectGroupModal').modal('hide');
}
else
alert(loadingRecipientsErrorMesage);
},
error: function(jqXHR, status, error, settings)
{
alert(loadingRecipientsErrorMesage);
},
complete: function(jqXHR, status, settings)
{
hideOverlay();
}
});
Díky.
- Vojtěch Dobeš
- Gold Partner | 1316
radas napsal(a):
Ahoj…
Řešení je prosté. Pokud potřebuješ unikátním způsobem obsloužit
specifický ajaxový požadavek, nesnaž se to udělat přes extenze (ty jsou
navržené pro řešení obecných reakcí na ajaxové požadavky). Stále
můžeš ajaxový callback zavěsit ručně (nedávej formuláři CSS třídu
ajax
) a pracovat s ním zcela libovolně.
$('#first-form').on('submit', function (e) {
$(this).netteAjax(e).done(function () {
// custom logic
});
});
- Kurtas
- Člen | 109
@vojtech.dobes Mam stejny problem jako @ji_ri_k ktery hlasil jiz pred dvema lety … V Safari opravdu vzdy probehne kazdy request 2×, staci odebrat history.ajax.js a uz to nedela, da se to nejak resit?
- akadlec
- Člen | 1326
@radas buď tak jak ti psal vojta a nebo pomoci podmíněných extension jak jsem tady pár postu opět zveřejňoval.
@Kurtas hele nejsi sám komu to nějak blbne ;) mě to taky nějak hapruje a to mám FF, když zapnu history.ext tak to dělá psí kusy, když vypnu tak je to ok. Ale zatím jsem to do hloubky nestudoval.
- radas
- Člen | 224
@akadlec Zkusil jsem ty podmíněné extensions. Funguje to správně v tom smyslu, že se zavolá na každém formuláři ta správná extension, ale problém je ten, že se mi vůbec nevykonají události success, error, complete. Zkrátka formulář se odešle a vrátí data, ale kód uvnitř metody success, který je má zpracovat, se nevykoná. Nemůžu přijít na to proč.
- Vojtěch Dobeš
- Gold Partner | 1316
Tak jsem to vnitřně dozpracoval, a otevřel jsem issue na
extensions, které jsou defaultně vypnuté (aka data-ajax-on
).
Nevím, kdy budu mít přesně čas to implementovat, ale pokud byste se někdo
našli, budu rád a uvítám PR. V onom issue jsem rozepsal, jak bych
si představoval implementaci a API.
- radas
- Člen | 224
@akadlec Už jsem přišel na tu příčinu. Problém byl v tom, že do pole settings.off se vždycky dostaly oba formuláře a tak proběhlo jen klasické odeslání AJAXem (obě extenze se ignorovaly). Nakonec jsem to vyřešil asi ne moc elegantně, ale funguje to. Bohužel $(this).netteAjax(e) jak psal @vojtech.dobes nemůžu použít (důvody jsou na dlouho), ale toto mi funguje:
$(':submit[name=...]').on('click', function()
{
$.nette.ext('prvni', null);
$.nette.ext('druha', null);
$.nette.ext('prvni',
{
//success, atd.
});
});
Druhou řeším úplně stejně.
- zool
- Člen | 144
Ahoj, chtěl jsem se zeptat. Potřeboval bych nějakým způsobém zajistit, aby se mi nespustili dva ajaxové požadavky. Dá se nějak udělat, aby nějaký požadavek byl nařazený než druhý?? Uvedu příklad třeba na chatu.
Mám chat kde se mi pravidelně updatují přízpěvky no a když odešlu další požadavek, který připisuje také snippet prizpevky, tak se to zbortí. Pokud se trefím mezi synchronizaci, tak to jede? děkuji
- Vojtěch Dobeš
- Gold Partner | 1316
Pro udržování jen jednoho běžícího requestu sloužít extenze
unique
, ve výchozím stavu by měla být zapnutá myslím. Pokud
potřebuješ něco trochu jiného nebo podobného, zkus to prosím popsat trochu
konkrétněji.
- Mysteria
- Člen | 797
Nevím, jestli to je to, co zrovna myslel @zool, ale chtěl bych se zeptat, jestli by šlo nějak jednoduše implementovat frontu AJAXových požadavků. Momentálně to funguje tak, že buď jsou unikátní, kdy nový požadavek přeruší ten stávající nebo neunikátní, kdy ale není zajištěno, že první odeslaný požadavek bude zpracován taky první, protože druhý se může dokončit rychleji a pak se první provede až jako druhý.
Takže šlo by nějak zajistit, že ty AJAXové požadavky dojdou přesně v takovém pořadí v jakém byly odpáleny? Myšleno tak, že i když se druhý požadavek vykoná dříve než první, tak se jeho success metoda spustí až poté, co se dokončí a spustí success metoda toho prvního?
- Vojtěch Dobeš
- Gold Partner | 1316
Lawondyss napsal(a):
Může mi někdo osvětlit, jak přes
$.nette.ajax
donutím šablonu invalidovat snippety?
Přes $.nette.ajax
nijak, invalidace snippetů se vyvolává na
serveru pomocí metody redrawControl
. $.nette.ajax
pouze zpracuje odpověď, která ze serveru přišla (a která může obsahovat
HTML kód invalidovaných snippetů).
- Lawondyss
- Člen | 106
Takže když mám:
// šablona
{snippet example}
{ifset $result}
{$result}
{/ifset}
{/snippet}
<script>
$.nette.ajax({
type: 'GET',
url: "/Example/example",
});
</script>
a
// ExamplePresenter
actionExample() {
$this->payload->result = $this->getResult();
$this->redrawControl();
}
tak co musím do $.nette.ajax
přidat pro překreslení
snippetů? Jestli jsem pochopil správně, tak callback po úspěšném volání
nastavím do success
. Všiml jsem si, že nette.ajax.js obsahuje
rozšíření snippets
. Můžu ho zneužít pro překreslení
snippetů?
- Vojtěch Dobeš
- Gold Partner | 1316
Tvůj kód by měl fungovat bez problémů až na drobný defekt – snippet
se jmenuje example
, takže musíš zavolat:
$this->redrawControl('example');
Metoda redrawControl
bez argumentu invaliduje snippet
bez jména.
Volání | V šabloně |
---|---|
$this->redrawControl() |
{snippet} |
$this->redrawControl('foo') |
{snippet foo} |
- David Matějka
- Moderator | 6445
@VojtěchDobeš n, redrawControl bez parametru invaliduje vsechny snippety v komponente/presenteru
- Vojtěch Dobeš
- Gold Partner | 1316
David Matějka napsal(a):
@VojtěchDobeš n, redrawControl bez parametru invaliduje vsechny snippety v komponente/presenteru
Pravda pravdoucí (zajímalo by mě, jestli můj dojem, že jde o změnu chování, je správný). Omlouvám se, to jsem nevěděl. Každopádně v takovém případě by měl Lawondyssův kód fungovat bez problémů.
- David Matějka
- Moderator | 6445
@VojtěchDobeš jo, chovani se zmenilo, ale uz je to nejakej ten patek :P
- Vojtěch Dobeš
- Gold Partner | 1316
David Matějka napsal(a):
@VojtěchDobeš jo, chovani se zmenilo, ale uz je to nejakej ten patek :P
Hahaha, tak pozadu zas nejsem :). Ale evidentně zapomínám, co jsem věděl.
- Lawondyss
- Člen | 106
Tak musím konstatovat, že ten kód mi nefunguje :-(
Hodím sem celý příklad, protože musím mít někde logickou chybu, kterou
nevidím.
// HomepagePresenter
public function actionTwistoChecked($transaction_id, $status, $reason)
{
// TODO: save $transaction_id
if ($status === 'accepted') {
$this->payload->message = 'Platba byla schválena.';
} else {
$this->payload->message = $reason;
}
$this->redrawControl('msg');
$this->sendPayload();
}
// Homepage/default.latte
{block script}
{include parent}
<script type="text/javascript">
tw.crypt = '{!$crypt}'; // do šablony posílá HomepagePresenter::renderDefault()
tw.init();
</script>
{/block}
{block content}
<div n:snippet="msg" style="border: 1px solid darkblue; padding: 10px;">
{ifset $message}
{$message}
{/ifset}
</div>
// twisto.js
// načítá se v layoutu před blokem script
var _twisto_config = {
public_key: config.twisto.publicKey,
script: 'https://static.twisto.cz/api/v2/twisto.js'
};
(function(e,g,a){function h(a){return function(){b._.push([a,arguments])}}var f=['check'],b=e||{},c=document.createElement(a);a=document.getElementsByTagName(a)[0];b._=[];for(var d=0;d<f.length;d++)b[f[d]]=h(f[d]);this[g]=b;c.type='text/javascript';c.async=!0;c.src=e.script;a.parentNode.insertBefore(c,a);delete e.script}).call(window,_twisto_config,'Twisto','script');
tw = {
crypt: '',
init: function twistoInit() {
tw.check(tw.crypt);
},
check: function twistoCheck(crypt) {
Twisto.check(crypt,
function twistoSuccessCheck(response) {
var link = config.url.twistoChecked; // /homepage/twisto-checked
$.nette.ajax({
type: 'GET',
url: link,
data: response
});
}
);
}
};
Celý proces je následovný:
- v
HomepagePresenter::renderDefault()
vypočítám$crypt
a pošlu do šablony - spustí se
twisto.init()
, které ověří hodnotu$crypt
twisto.twistoCheck()
vrátí status ověření- status se AJAXem na
HomepagePresenter::actionTwistoChecked()
- status se zpracuje, nastaví se
$message
a překreslí se snippet
Jenže snippet se nepřekreslí.
- Vojtěch Dobeš
- Gold Partner | 1316
Mám dojem, že problém dělá $this->sendPayload()
. Zavolá
se před tím, než se snippety vyrenderují.
- OKweb
- Člen | 12
Ahojte, mohli by ste mi, prosím, poradiť?
Používam nette.ajax.js bez problémov, keď chcem spracovať formulár, tak ako je, ajaxovo, iba nastavím class=„ajax“ a cez $.nette.ext mám nastavené, čo sa má vykonať before, success atď.
Moja otázka znie, ako by som mohol zmeniť nastavenia ajaxového požiadavku pôvodne načítané z formulára, teda pozmeniť odosielané dáta, metódu, prípadne url? Ak v „before“ niečo vo formulári zmením, napr. atribút method, vykonávanú akciu to už neovplyvní, takže v tom štádiu to je už zrejme niekde načítané a meniť to treba tam.
Ďakujem!
- mfajfr
- Člen | 26
Ahoj,
momentálně tápu s odesláním (POST) formuláře přes AJAX.
Pokud to dobře chápu, tak buď musím mít nette.ajax.js nebo jquery.nette.js.
Mám tedy to druhé.
Pak mám skript, který odešle formuláře (nebo si to aspoň myslím):
<script>
$(function () {
$('.product-quantity').on('change', function (){
$.post(window.location.href);
});
});
</script>
V metodě, která zpracovává formulář (bez AJAXu funguje), mám
momentálně překreslení celé stránky, čili
$this->redrawControl() // presenter;
Přes Chrome debug vidím 200 OK, ale v response je stále stará hodnota.
Předem díky za odpověď.
- akadlec
- Člen | 1326
@mfajfr tak pokud to chceš posílat přímo pomocí jQuery tak se prosímtě podívej do dokumentace jak se používá
- akadlec
- Člen | 1326
@mfajfr: tak pak musíš postupovat podle návodu pro nette.ajax.js pro které je tohle téma
- Vojtěch Dobeš
- Gold Partner | 1316
OKweb napsal(a):
Ahojte, mohli by ste mi, prosím, poradiť?
Používam nette.ajax.js bez problémov, keď chcem spracovať formulár, tak ako je, ajaxovo, iba nastavím class=„ajax“ a cez $.nette.ext mám nastavené, čo sa má vykonať before, success atď.
Moja otázka znie, ako by som mohol zmeniť nastavenia ajaxového požiadavku pôvodne načítané z formulára, teda pozmeniť odosielané dáta, metódu, prípadne url? Ak v „before“ niečo vo formulári zmením, napr. atribút method, vykonávanú akciu to už neovplyvní, takže v tom štádiu to je už zrejme niekde načítané a meniť to treba tam.
Ďakujem!
Můžeš využít událost prepare
. Dostává jako argument
settings
, ale narozdíl od before
se volá ještě
před $.ajax
, takže je tam možné upravit cokoliv.
- mfajfr
- Člen | 26
@akadlec Díky moc, už se mi povedl rozjet AJAX a moc se líbí. Ovšem se našel nový problém, který se již tady řešil, a to je, že po překreslení už zase nejde.
Udělal jsem to dynamické řešení, resp. použil řešení od @VojtěchDobeš (napsáno v jiném tématu):
<script>
(function(window, $, undefined) {
$.nette.ext('number-onchange', {
load: function () {
$(document).on('change', '[name="' + productFormData.formNames.quantityName + '"]', function (e) {
e.preventDefault();
$('form[data-idproduct="' + $(this).data('idproduct') + '"]').submit();
});
}
});
})(window, window.jQuery);
</script>
Dle ChromeDevTools se mi poprvé přijme „json“, ale pak už „html“,
přičemž se mi pak odeslali dvakrát hned po sobě (pak 4× apod.)
To jsem zkusil vyřešit:
<script>
$(document).off('change', '[name="' + productFormData.formNames.quantityName + '"]');
</script>
To mi vyřešilo problém s několikanásobným odesíláním, ale stále přijímám pouze „html“ a nikoliv „json“.
EDIT: Co jsem si všiml, tak v případě druhém AJAXu se neodesílá vůbec data formuláře.
Editoval mfajfr (28. 3. 2015 13:09)
- MW
- Člen | 626
Zdravim,
nevíte někdo prosím, jak nejlepe vypnout spinner při volani modalniho okna?
a href="{plink editModal! 'id' => $primary}" type="button" class="ajax btn btn-warning btn-xs"><span class="glyphicon glyphicon-edit"></span></a>
Mam doplněk:
$.nette.ext('spinner', {
init: function () {
this.spinner = this.createSpinner();
this.spinner.appendTo('body');
},
start: function (jqXHR, settings) {
if (!settings.nette) { //fix pro modal !
return;
}
this.spinner.css({
// left: '50%',
// top: '30%'
left: settings.nette.e.pageX,
top: settings.nette.e.pageY
});
this.spinner.show(this.speed);
},
complete: function () {
this.spinner.hide(this.speed);
}
}, {
createSpinner: function () {
return $('<div>', {
id: 'ajax-spinner',
css: {
display: 'none'
}
});
},
spinner: null,
speed: undefined
});
Děkuji za radu
Editoval MW (30. 3. 2015 13:59)
- pidiclovek
- Člen | 91
Ahoj,
koukal jsem do zdrojáku knihovny a myslím že nejde udělat něco jako:
$.nette.ajax({
type: 'GET',
url: $link,
append: true
});
na straně javascriptu. Vím o přepínači data-ajax-append, ten ale
použít nemohu protože se
mi append má použít jen někdy, potřebuji to tak řešit na straně js a ne
v latte. Otázka zní – přehlédl jsem to a jde to, či to budu muset
očůrat a napsat si append sám? Jak případně na to?
Díky!
Editoval pidiclovek (30. 3. 2015 23:28)
- Vojtěch Dobeš
- Gold Partner | 1316
pidiclovek napsal(a):
Ahoj,
koukal jsem do zdrojáku knihovny a myslím že nejde udělat něco jako:
$.nette.ajax({ type: 'GET', url: $link, append: true });
na straně javascriptu. Vím o přepínači data-ajax-append, ten ale použít nemohu protože se
mi append má použít jen někdy, potřebuji to tak řešit na straně js a ne v latte. Otázka zní – přehlédl jsem to a jde to, či to budu muset očůrat a napsat si append sám. Jak případně na to?Díky!
Podpora je skutečně jen přes datový atribut v HTML. Nicméně tento
atribut je zpracováván až v rozšíření
snippets
. Její chování si lze však přepsat
k obrazu svému:
$.nette.ext('snippets')applySnippet = function ($el, html, back) {
// ...
};