AJAX vagyis AJAJ a Drupalban
A drupal.hu fórumán tette fel andrew a kérdést, hogy hogyan tudja megoldani a Drupal-lal, hogy egy legördülő lista tartalma egy másik "select" mező változásakor automatikusan frissüljön. A megoldáshoz modul fejlesztési, form API és minimális jQuery ismeretekre lesz szükségünk. A megértést elősegítendő készítettem egy deszkamodellt, hogy a hosszadalmas és ködös magyarázkodás helyett egy konkrét példán keresztül tudjam bemutatni a megoldást.
Az elkészített modul 3 fájlból áll. Az probaform.info fájl a minden modulnál elengedhetetlen információkat tartalmazza. A prbaform.module a php kódot, a probaform.js pedig a JavaScript kódot tartalmazza.
A probaform.module függvényei.
probaform_menu
'formproba', 'callback' => 'formproba_page', 'title' => 'Form próba', 'access' => user_access('access content'), ); $items[] = array( 'path' => 'formproba/data', 'callback' => 'formproba_data', 'access' => user_access('access content'), 'type' => MENU_CALLBACK); return $items; } ?>Két útvonalat definiálunk. Az egyik (probaform) egy oldal, mely a formot jeleníti meg. A tesztelést megkönnyítendő a menübe is elhelyeztük, csak rá kell kattintani. A második útvonal (probaform/data) mely a JS kérésekre fog válaszolni.
probaform_page
Ez a függvény fogja megjeleníteni a formot, valamint a probaform.js fájlt betöltéséről gondoskodik. Fontos, hogy ne a sminkbe hegesszük bele a .js fájljaink betöltését, hanem a drupal_add_js függvénnyel hívjuk be azokat. A Drupal ugyanis csak akkor fogja beletenni a header részbe a drupal.js és jquery.js hivatkozásokat, ha az szükséges. A drupal_add_js függvénnyel tudjuk jelezni a Drupal-nak, hogy szeretnénk azokat használni.
probaform_form
'select', '#title' => 'Első választás', '#default_value' => 1, '#options' => array(1 => 'gyümölcs',2 => 'növény',3 => 'állat',), ); $form['select2'] = array( '#type' => 'select', '#title' => 'Második választás', '#options' => isset($_POST['select1'])?formproba_get_select2($_POST['select1']):formproba_get_select2(1), ); $form['submit'] = array( '#type' => 'submit', '#value' => 'Elküld', ); return $form; } ?>A formot leíró kódot tartalmazza. Látható, hogy két select mezőnk van valamit egy submit gombunk. Igazából a második lista (select2) options része szorul magyarázatra és az, hogy miért nem kell használnunk a #DANGEROUS_SKIP_CHECK direktívát. A magyarázat előtt tisztázzunk pár dolgot!
Mi is az a DANGEROUS_SKIP_CHECK nem dokumentált direktíva?
Biztonsági megfontolásból a Drupal csak olyan választásokat fogad el a klienstől, mely a kiküldött, vagyis a szerver oldalon generált lehetőségek között szerepel. Abban az esetben, ha egy választó lista tartalmát nem a szerveren, hanem a kliensen építjük fel akkor a Drupal hibaüzenetet fog adni, ha olyan elemet választottunk ki, ami nem szerepel a lehetőségek között. Nem lehet tudni ugyanis, hogy ez a szabályos működés vagy egy támadási kísérlet eredménye. Ezt a direktívát csak megfelelő körültekintés mellet javasolt használni!
Hogyan működik a Drupal form feldolgozása?
Megnézzük, hogy jött-e adat? Nem jött, akkor kirajzoljuk a formot. Jött adat, akkor ellenőrizzük, hogy helyes-e. Nem helyes adatok esetén újra kirajzoljuk a formot, de a helyes adatokat már megjelenítjük, hogy a felhasználónak ne kelljen azokat újra megadni. Helyes adatok esetén feldolgozzuk a kapott adatokat.
A select2 beviteli mező értékeinek előállításakor megnézzük, hogy jött-e adat, ha jött, akkor a választásnak megfelelő listát töltjük be, ha nem jött akkor az elsőt. Mivel ekkor ugyan az a lista a kliens oldalon és az ellenőrzésnél a Drupal nem fog szólni a nem megfelelő adatok miatt.
formproba_form_submit
'.print_r($form_values,true).''); } ?>Ez a függvény végzi a form feldolgozását. Jelen esetben csak annyit csinál, hogy kiírja az adatokat.
formproba_data
Ez a függvény végzi a kérések kiszolgálását. Semmi mást nem csinál, mint kiírja a kimenetre a lehetőségeket tartalmazó tömb JSON reprezentációját. Tesztelni úgy lehet, hogy a címsorba beírjuk, hogy ?q=formproba/data/1
formproba_get_select2
'alma','2'=>'körte','3'=>'barack'); case 2: return array('4'=>'fa','5'=>'bokor','6'=>'virág'); case 3: return array('7'=>'nyuszi','8'=>'róka','9'=>'malac'); default: return false; } } ?>Mivel a lehetőségeket tartalmazó tömbre két helyen is szükségünk van ezért azt egy függvénybe burkoltam.
formproba.js függvényei
// $Id$
if(Drupal.jsEnabled){
$(document).ready(formproba_init);
}
function formproba_init(){
$('#edit-select1').change(function(){
$.getJSON("/",{q: 'formproba/data/' + $(this).val()},formproba_feldolg);
});
}
function formproba_feldolg(j){
options = '';
for(i in j){
options += '';
}
$("#edit-select2").html(options);
}
formproba_init
Ez a függvény az oldal betöltődésekor fut le. Beállítja, hogy a select1 mező megváltozásakor egy AJAJ kérés fusson le. Az adatok feldolgozását, azok megérkezésekor a formproba_feldolg függvény fogja végzi.
formproba_feldolg
A megkapott adatokból elkészítjük a megfelelő HTML kódot és lecseréljük a select2 listáját erre.
Csatolmány | Méret |
---|---|
![]() | 76 byte |
![]() | 393 byte |
![]() | 1.6 KB |
Hozzászólások
Pont valami ilyesmire lett
Pont valami ilyesmire lett volna szükségem egy projectnél (csak ott 3 szintű), de sajnos akkoriban nem érkezett válasz a kérdésre, így egy másik rendszert (cakePHP) választottam.
Explorer / Firefox
Explorer / Firefox különbség
A megoldás szuperül működik nekem Firefox-ból, de Explorer-ben üres marad a 2. lista. A formproba_data függvény javasolt tesztje (formproba/data/1) az Explorer-ben is rendben lefut.
A probléma a böngészők és beállításaik környékén lehet, vagy esetleg a megoldásban?
Köszönöm,
Doka
A echo drupal_to_js(); exit;
A
echo drupal_to_js(); exit;
helyett nem lenne elég egydrupal_json()
? Ha nem, miért nem?Az exit() tényleg hülyeség,
Az
exit()
tényleg hülyeség, ki is szedtem. Ez a leírás azonban még 5.x Drupalra készült és ott még nem voltdrupal_json()
függvény. Abban igazad van, hogy ma már így kéne!pp
Szia! Akkor tehát úgy kell
Szia!
Akkor tehát úgy kell kinéznie 6-os alatt az említett sornak, hogy
drupal_json(formproba_get_select2(arg(2))); ?
Lehet, hogy iszonyatosan láma kérdés, de mit jelent itt az arg(2)?
Ha megnézed a formproba.js-t
Ha megnézed a formproba.js-t akkor láthatod, hogy az ajax kérés úgy néz ki, hogy:
Látszik, hogy az útvonal az a
'formproba/data/' + $(this).val()
. Ez a Drupalban úgy értelmeződik, hogy az arg(0) az a fromproba, az arg(1) az a data és az arg(2) pedig az a szám, amit át akarunk adni. Szóval a rövid válasz az az, hogy a fő kategória azonosítója.Így már érthető számomra
Így már érthető számomra minden, köszönöm szépen a választ.
Viszont még most sem akar működni, ezért ismét a segítségedet kérném, ha nem baj. Az imént említett sorban meghívódik a
formproba_feldolg
függvény, de nekem nem fut le. Beletettem egy alertet, hogy lássam, mikor hajtódik végre, és arra jutottam, hogy ha nem kap semmilyen paramétert a hívásnál, akkor egyáltalán nem fut le. Ha zárójelben megadok neki valamilyen paramétert (pl. "abc"), akkor bizony lefut, és a select2 mezőmben ott lesznek az új választási lehetőségek ('a', 'b', 'c'). Ez így teljesen jó, most már csak annyi kellene, hogy tudjam neki az ajax kérés eredményét átadni, azaz a JSON reprezentációt dolgoztassam fel vele.Tudnál segíteni?
A formproba_menu-t teljesen
A formproba_menu-t teljesen újra kell írni! Hatos alatt azért nem megy.
pp
Ezt természetesen megtettem,
Ezt természetesen megtettem, nem ez a problémám. Az előző hozzászólásomban leírtam, mi nem működik. Minden más jó, annyi a baj, hogy a
formproba_feldolg
függvény nem kapja meg az ajax kérés eredményét. Le sem fut a függvény azért, mert várna egy paramétert. Minden más okés, csak ez a baj, ebben biztos vagyok.Próbálkoztam, és végül most
Próbálkoztam, és végül most már működik. Módosítanom kellett hozzá az ajaxos hívás sorát, mégpedig így:
Köszönöm a nagyszerű posztot és a segítséget! ;)
formproba_menu-t átírva
formproba_menu-t átírva remekül működik.
Nagyon köszönöm, sokat segített!