2011-12-28 113 views
0

我想在Drupal中創建一個表單,因此可以將多個元素添加到表單中。例如,一個頁面可能包含一個事件的數據,那麼該事件可能有多個日期。所以,我有,看起來像一個形式:Drupal AJAX回調只調用一次

/** 
* Implements hook_form_alter(). 
*/ 
function addextra_form_alter(&$form, &$form_state) { 
    if ($form['#form_id'] == 'test_content_node_form') { 
    $form['elements_table'] = array(
     '#theme' => 'table', 
     '#title' => 'Elements already added', 
     '#header' => array('Item', 'Remove'), 
     '#empty' => 'No elements', 
     '#prefix' => '<div id="elements-table">', 
     '#suffix' => '</div>', 
    ); 
    $form['add_elements'] = array(
     '#title' => 'Add another element', 
     '#type' => 'fieldset', 
     '#collapsible' => TRUE, 
     '#collapsed' => FALSE, 
    ); 
    $form['add_elements']['add_content'] = array(
     '#type' => 'textfield', 
     '#description' => t('Add an element to the table'), 
     '#title' => t('Add another item'), 
     '#size' => '12', 
     '#maxlength' => '60', 
     '#prefix' => '<div id="addextra_content">', 
     '#suffix' => '</div>', 
    ); 
    $form['add_elements']['add_another_btn'] = array(
     '#type' => 'button', 
     '#name' => 'add_another', 
     '#button_type' => 'submit', 
     '#executes_submit_callback' => FALSE, 
     '#value' => 'Add another', 
     '#ajax' => array(
      'callback' => 'addextra_element_to_table', 
     ), 
    ); 
    } 
} 

當「add_another_btn」被點擊,它會運行Ajax回調「addextra_element_to_table。

該回調是:

function addextra_element_to_table(&$form, &$form_state) { 
    $form['elements_table']['#rows'][] = array($form_state['values']['add_content'], l('Remove Item', '#')); 
    drupal_add_js(drupal_get_path('module', 'addextra') . '/addextra.js'); 
    return array(
     '#type' => 'ajax', 
     '#commands' => array(
      ajax_command_replace('#elements-table', render($form['elements_table'])), 

    ), 
); 
} 

叫JS文件替換輸入字段爲 ''

(function ($) { 
    $('#edit-add-content').val(''); 
})(jQuery); 

的VAL但只有這個回調函數被調用一次。我相信這是因爲一旦被調用,行爲必須重新被附加。對不起,我的無知 - 我不知道如何實現這一點。誰能幫我嗎?這將非常感激。提前致謝。

+0

我不是Drupal的專家,但是你所做的是在已經加載的html頁面中一次又一次添加相同的js文件,並期望每次調用'$(document).onload()'事件?看起來很奇怪。爲什麼使用Ajax來實現?難道你不能'克隆'一個(最終)隱藏的節點嗎? – Stan 2011-12-28 02:50:05

+0

我可以刪除js,但替換爲新元素的表單也不起作用。它不會在回調中添加'#row'數據的操作。 – Deshiknaves 2011-12-28 03:00:04

+0

我已經移動了drupal_add_js,它按預期工作。每當我爲add_content添加一個新值時,它都會運行並替換表。但它不添加到「#rows」,它只是用新值替換行,而不是加入一個新元素,則表更換表。任何想法將不勝感激。我知道還有其他的方法可以實現這一點,但我現在只想弄清楚如何以這種方式實現它,所以我可以在將來使用這種方法。 – Deshiknaves 2011-12-28 08:49:12

回答

4

問題是render(),基本上只是調用drupal_render(),不處理#ajax元素,它只是被忽略。在致電render()之前,您可能想嘗試通過ajax_pre_render_element()傳遞元素。

這就是說,我個人沒有很好的經驗,試圖在正常的調用順序之外重用Drupal函數,特別是不使用窗體。我更喜歡堅持頂級功能,如drupal_get_form。我在調試器中多次跟蹤這些函數,並且他們按照精確的順序執行一系列的操作,當你想重用這些函數的時候很難保留下來。

要改變與AJAX回調一種形式,我總是喜歡兩種策略之一:

  • 在回調,調整$form爭論的內容和做return $form。這要求您將#ajax['wrapper']設置爲原始元素(您的案例中的按鈕)上的表單的id(標記中的id屬性的值,用於CSS)。然後Drupal可以完成整個表單的瀏覽器,而瀏覽器取代了整個表單。 Drupal負責保存已經輸入的值等。
  • 或者,您可以讓回調返回一組命令,這些命令在DOM上做了非常特定的修改。在你的情況下,這將是創建和追加新行的命令。請記住,與ajax_command_invoke(),你有你的處置整個jQuery武庫。

從這兩種策略中,我通常更喜歡第二種策略,因爲它對於小小的調整似乎更加優雅。然而,如果你想建立在Drupal的渲染上,或者如果你對窗體有更大的改變,你應該使用第一個。

作爲一個附註,你知道有drupal.stackexchange.com? Drupal可能很特別,在這個網站上,你會發現更多的細節專家。

+0

我有同樣的問題,並做「返回$表格;」在頂級id的回調中立即修復它(vs「return $ form ['some_element'];」到一個有針對性的id)。這是迄今爲止我能夠做出的唯一解決方案。謝謝! – 2013-06-10 23:00:26

+0

+1指向drupal.stackexchange.com – 2014-06-19 09:38:17