Alapszintű AHAH Drupal 6 alatt

CSÉCSY László's picture
in

Feladat: egy űrlapon adott egy szövegmező (például partner neve), valamint egy legördülő (például a hozzá tartozó szerződések). Az oldal újratöltése és többoldalas űrlap használata nélkül a szövegmező (partnernév) kitöltése után töltsük fel a legördülőt (szerződéseket) a szövegmező tartalma alapján.

Megvalósítás: szükségünk van két menüelemre, melyek egyrészt az űrlapot, másrészt az AHAH kérést kezelik.

function ahahdemo_menu() {
  $items['ahahdemo'] = array(
    'title'            => 'AHAH Demo form',
    'access arguments' => array('access content'),
    'page callback'    => 'drupal_get_form',
    'page arguments'   => array('ahahdemo_ahahdemo_form'),
  );
  $items['ahahdemo/js'] = array(
    'access arguments' => array('access content'),
    'page callback'    => 'ahahdemo_ahahdemo_js',
    'type'             => MENU_CALLBACK,
  );
  return $items;
}


Az űrlapot a szokásos módon állítjuk elő: oldalt fogunk generáltatni, ahol a drupal_get_form() függvénynek adjuk át paraméterül azon saját függvényünk nevét, mely az űrlap adataival tér vissza.
Az AHAH kérés kezelésekor szintén "oldalt" állítunk elő, azonban ezt egyrészt nem jelenítjük meg a menüben (csak zavaró lenne), másrészt a teljes "oldalt" a saját függvényünk állítja elő.

Szükségünk lesz tehát az (üres) űrlap adatait összeállító függvényre is.

function ahahdemo_ahahdemo_form($form_state) {
  $form = array();
  $form['textfield1'] = array(
    '#type' => 'textfield',
    '#title' => t('Text field 1'),
    '#ahah' => array(
      'path' => 'ahahdemo/js',
      'wrapper' => 'edit-dropdown1-wrapper',
      'progress' => array(
        'type' => 'none',
      ),
    ),
  );
  $form['dropdown1'] = array(
    '#type' => 'select',
    '#title' => t('Drop down 1'),
    '#options' => array(t('< Empty >')),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}


A trükk a szövegmező #ahah elemében van, méghozzá többszörösen. A path elem mutatja meg, hogy a kliensoldali jQuery milyen elérési útra küldje el az űrlapot a háttérben (innen az AHAH első és utolsó betűje: Asynchronous és HTTP). A wrapper elem mutatja meg a megjelenített űrlap azon elemének azonosítóját (HTML id-jét), melynek tartalmát a visszakapott HTML-re kell cserélni (innen az AHAH középső két betűje: HTML és And). Ha textfield típusú űrlapelemhez rendeljük az #ahah elemet, akkor a kérés a szövegmező elhagyásakor fut le - ami nekünk pontosan megfelel.
A progress elem none értéke egy dokumentálatlan lehetőség: itt elvileg a throbber és a progress közül lehetne választani - előbbi hatására körbeforgó, utóbbiéra bitkolbász animgifet jelenítene meg a jQuery arra az időre, míg az AHAH kérés lefut. Mivel a none értéket nem ismeri a misc/ahah.js, ezért nem fog megjeleníteni semmit - így még kevésbé fogja kedvenc megrendelőnket zavarni a villódzás.

Egyetlen lépés van már csak hátra: az AHAH/jQuery kéréskor lefuttatandó PHP függvény.

function ahahdemo_ahahdemo_js() {
  // Új elem felépítése.
  $new_element = array(
    'dropdown1' => array(
      '#type' => 'select',
      '#title' => t('Drop down 1'),
    ),
  );
  switch ($_POST['textfield1']) {
  case 3:
    $new_element['dropdown1']['#options'][3] = t('Three');
  case 2:
    $new_element['dropdown1']['#options'][2] = t('Two');
  case 1:
    $new_element['dropdown1']['#options'][1] = t('One');
  default:
    $new_element['dropdown1']['#options'][0] = t('< Empty >');
  }
  // Űrlap felépítése.
  $form_state = array('submitted' => FALSE);
  $form_build_id = $_POST['form_build_id'];
  // Az új elem írja felül a régit - ha nem teszi, a Drupal Form API nem fog
  // tudni róla, így nem fogja elfogadni az új választási lehetőségeket -
  // illetve egész pontosan kitöltetlen lesz a
  // $form_state['values']['dropdown1'].
  if (!$form = form_get_cache($form_build_id, $form_state)) {
    exit();
  }
  $form['dropdown1'] = $new_element;
  form_set_cache($form_build_id, $form, $form_state);
  $form += array(
    '#post' => $_POST,
    '#programmed' => FALSE,
  );
  // Űrlap újraépítése.
  $form = form_builder('ahahdemo_ahahdemo_form', $form, $form_state);
  // Új űrlapelem kibontása.
  $new_form = $form['dropdown1'];
  unset($new_form['#prefix'], $new_form['#suffix']); // Dupla csomagolás megakadályozása.
  $new_form['#attributes']['class'] = empty($new_form[$delta]['#attributes']['class']) ?
    'ahah-new-content' :
    $new_form[$delta]['#attributes']['class'] .' ahah-new-content';
  // Az esetleges üzenetek kerüljenek az új elem fölé.
  $output = theme('status_messages') . drupal_render($new_form);
  drupal_json(array('status' => TRUE, 'data' => $output));
}


A dolog lényege a következő: a Drupal Form API-ja nem enged olyan értéket beküldeni (legalábbis jelen példánál maradva a legördülőben nem), amely az űrlap összeállításakor nem szerepelt a lehetséges értékek között - márpedig az űrlap generálásakor nem tudhatjuk, hogy egy később bekérendő partnerhez melyik szerződés(ek) tartoz(nak) -, ezért a generált űrlapot nem csak megjeleníti, hanem gyorsítótárban (adatbázistáblában) tárolja is a Drupal. Ennek megfelelően nem elég generáltatni egy új legördülőt, mely a megfelelő értékeket tartalmazza, hanem azt a Drupal Form API tudomására is kell hozni, azaz elő kell bányászni a gyorsítótárból az űrlapot, a megfelelő részét felülírni, újraépíttetni az űrlapot (ezáltal felülírva a gyorsítótárban tárolt változatot), majd a megfelelő részét visszaküldeni a böngészőnek - s nem XML-ként (mint AJAX esetén), hanem HTML-ként, hogy kliensoldalon ne kelljen a kelleténél többet foglalkozni a feldolgozással.

A csatolt példa megvalósításban a szövegmező értéke 1, 2 vagy 3 lehet ahhoz, hogy a legördülőben változzon is az alapértelmezés.

(A bejegyzés megírásában ez a cikk volt segítségemre.)

AttachmentSize
ahahdemo-6.x.tgz1.31 KB

Comments

A cikkért ezer hála! Az oldal

A cikkért ezer hála!
Az oldal meg talán a legszebb magyar drupal oldal, amit láttam.

Syndicate content