NAJA – svazani s jinym elementem nez odkazem, formularem

pp
Člen | 48
+
0
-

Ahoj,
zacinam si hrat s AJAXem resp. novou NAJA knihovnou – navazani vsech elementu odkazu, submitu funguje
ale pro napojeni na datagrid a jeho inline editaci bunky potrebuju vyvolat AJAX pozadavek pri opusteni <td> bunky (onblur)
Mel jsem zato ze staci zadat pri inicializaci.

document.addEventListener('DOMContentLoaded', () => {
    var element = document.querySelector('#id_table_td');
    naja.uiHandler.bindUI(element);
    naja.initialize()
});

Bohuzel pro me (jelikoz s JS a AJAXem mam minimum zkusenosti) je NAJA dokumentace prilis stroha, pomohlo by vic konkretnich prikladu.
Poradi nekdo?

jiri.pudil
Nette Blogger | 1028
+
+1
-

Ahoj, Naju skutečně zajímá jenom click na odkaz s třídou ajax nebo odeslání takového formuláře. Pokud chceš vyvolat ajaxový request i jinou interakcí, musíš si to zařídit sám:

document.addEventListener('DOMContentLoaded', () => {
    naja.initialize();

    const element = document.querySelector('#id_table_td');
    element.addEventListener('blur', () => naja.makeRequest('GET', '/url'));
});
pp
Člen | 48
+
0
-

Dekuju za nasmerovani ale porad v tom plavu.
Chtel bych pro vsechny interakce (kliknuti a odeslani formu) zobrazit po dobu zpracovani spinner a zmenit pruhlednost pozadi.
Pouzil jsem tvoji ukazku z dokumentace a to funguje super. Jen nechapu kde se bere ten {detail}

class LoadingIndicatorExtension {
    constructor(globalSpinner) {
        this.globalSpinner = globalSpinner;
    }
    initialize(naja) {
        this.globalSpinner = document.querySelector(this.globalSpinner);
        naja.uiHandler.addEventListener('interaction', this.locateSpinner.bind(this));
        naja.addEventListener('start', this.showSpinner.bind(this));
        naja.addEventListener('complete', this.hideSpinner.bind(this));
    }
    locateSpinner({detail}) {
        detail.options.spinner = this.globalSpinner;
    }
    showSpinner({detail}) {
        detail.options.spinner.classList.add('fa','fa-spinner','fa-spin','fa-3x','fa-fw');
        document.body.classList.add('body-transparent');
    }
    hideSpinner({detail}) {
        document.body.classList.remove('body-transparent');
        document.body.contains(detail.options.spinner) && detail.options.spinner.classList.remove('fa','fa-spinner','fa-spin','fa-3x','fa-fw');
    }
}
naja.registerExtension(new LoadingIndicatorExtension('#globalSpinner'));

Nicmene chtel jsem to rozsirit o operaci ‚blur‘ zkusil jsem to resit podobne ale nefunguje to (funkce startSpinner a completeSpinner se nespusti). Zajimavy ze pokud to misto ‚blur‘ navazu treba na ‚mouseover‘ tak se funkce probehnout.

function startSpinner(el){
    el.classList.add('fa','fa-spinner','fa-spin','fa-3x','fa-fw');
    document.body.classList.add('body-transparent');
};

function completeSpinner(el){
    el.classList.remove('fa','fa-spinner','fa-spin','fa-3x','fa-fw');
    document.body.classList.remove('body-transparent');
};

document.addEventListener('DOMContentLoaded', () => {
    naja.initialize();
    const el = document.querySelector('#globalSpinner');
    const hostnames = document.querySelectorAll('#snippet-ubntSta2Grid-tbody .td-hostname');
    hostnames.forEach(function(element) {
        element.addEventListener('blur', (event) => {
            naja.addEventListener('start', startSpinner(el), true);
            naja.addEventListener('complete', completeSpinner(el), true);
        });
    });
});
jiri.pudil
Nette Blogger | 1028
+
+4
-

Neber si to prosím nijak špatně, ale asi bych na tvém místě věnoval trochu víc pozornosti JavaScriptu a DOM API, než se pustíš do takovéhle integrace. Z toho kódu křičí, že moc nevíš, co děláš :)

Předně nemá smysl pro každý element navěšovat listenery, to by mělo proběhnout jenom jednou a ideálně v tom rozšíření. Pro každý element už pak chceš jen na blur vyvolat request, což je kód z mého předchozího příspěvku. O zobrazení a skrytí spinneru by se pak mělo postarat právě ono rozšíření.

Zadruhé: addEventListener obecně očekává listener, tj. funkci. Ty ovšem místo předání reference na funkci tuto funkci rovnou voláš (startSpinner(el)), stane se tedy to, že při bluru se správně zavolá zaregistrovaná arrow function, v rámci které se ovšem hned zobrazí a zase schová spinner (protože tam ty funkce rovnou voláš) a výsledky těch dvou volání se zaregistrují jako listenery v Naja – ty výsledky jsou mimochodem undefined, protože ani jedna z těch funkcí nic nevrací.


Myslím že chceš něco takového:

document.addEventListener('DOMContentLoaded', () => {
    // Zaregistruju si rozšíření, které se mi pak ve správné momenty postará o zobrazení a skrytí spinneru.
    naja.registerExtension(new LoadingIndicatorExtension('#globalSpinner'));

    // Inicializuji Naju.
    naja.initialize();

    // To chování na blur je mimochodem potřeba zaregistrovat nejen teď, ale i po každém překreslení snippetů,
    // protože překreslením se nahradí elementy v DOMu, na které jsou ty listenery navěšené. Proto si to chování
    // nejdříve vytáhnu do funkce:
    const bindBlur = (container) => {
        const hostnames = container.querySelectorAll('.td-hostname');
        hostnames.forEach((element) => {
            // při bluru už jen odešlu request, o spinner se postará zaregistrované rozšíření
            element.addEventListener('blur', () => naja.makeRequest('GET', '/url'));
        });
    };

    // Funkci bindBlur pak zavolám při inicializaci...
    bindBlur(document.getElementById('snippet-ubntSta2Grid-tbody')); // <-- Tady bych se mimochodem přimlouval za jiný selektor, třeba pomocí data atributu, který tomu elementu přiřadíš explicitně. ID snippetu se generuje, takže nad ním nemáš takovou kontrolu a může se ti to v budoucnu rozbít.

    // ...a pak i po překreslení snippetu
    naja.snippetHandler.addEventListener('afterUpdate', ({detail}) => bindBlur(detail.snippet));
});

Jinak všechny události, které vyvolává Naja, jsou instance CustomEvent, odtud se tedy bere detail. Ta syntax s kudrnatými závorkami v parametru je destructuring assignment.

pp
Člen | 48
+
+1
-

Mas pravdu, je to z me strany opravdu strelba pokus omyl :-) A moc si cenim tve vstricnosti a hlavne hodnotne odpovedi – mohlo to byt jen „nejdriv si to nastuduj a pak se ptej“. Chapu, ze pro zkusenejsi to je ztrata casu – o to vetsi dik.

jiri.pudil
Nette Blogger | 1028
+
+1
-

V pohodě, všichni jsme někdy nějak začínali :) rád jsem pomohl, neberu to úplně jako ztrátu času, ale i jako splátku toho, že v mých začátcích pomáhali a radili jiní mně. Třeba to zas někdy oplatíš ty budoucím začátečníkům a koloběh bude pokračovat ;)

Šaman
Člen | 2634
+
0
-

Přiznám se, že ve skutečném JS taky totálně plavu. S nette.ajax.js se dalo v JQuery splácat ledacos – různé chytré formuláře, potvrzování akcí, vyskakování nějakých nápovědných bublin – víc jsem toho asi nikdy nepotřeboval. Jo a závislé selectboxy přes snippety.

V Naje ale plavu totálně, vesměs mám jen oživené ajax snippety a zbytek jedině hotová řešení.

Editoval Šaman (19. 1. 2021 15:42)

Petr Parolek
Člen | 455
+
0
-

Přiznám se taky, totálně plavu v JS. Včera bez pomoci kamráda, bych vůbec nezvládl zaslat PR na vylepšení Naji a ještě není vůbec ideální https://github.com/…aja/pull/207 , raději implentaci nechám na @jiri.pudil .

Editoval ppar (19. 1. 2021 16:42)

dakur
Člen | 493
+
+1
-

On se frontend strašně posunul dopředu a vůbec to není jen pozlátko – má dost velký vliv na to, jak se s danou aplikací pracuje uživateli. @jiripudil dělal už i nějaké kurzy moderního javascriptu, třeba by udělal nějaký další, kdybyste o to stáli. Můžu ho jen doporučit, rozumí tomu, umí skvěle vysvětlovat a má trpělivost – prostě dobrý učitel. 👍