将AHAH表单元素嵌入到theme_table生成的表中(Drupal)

时间:2009-12-30 18:50:23

标签: php ajax drupal drupal-6

我正在尝试在我使用theme_table / theme('table',..)生成的表格中包含Drupal表单元素。具体来说,我试图包含一个附有AHAH的提交按钮。

目前,我只是在每一行中包含一个对drupal_render的调用,以呈现我动态生成的AHAH元素。按钮呈现正常,但没有连接AHAH。

所以,我的问题是:有没有办法将AHAH附加到只有drupal_render的东西?

如果没有,我怎样才能将AJAX / AHAH调用附加到theme_table生成的表中的元素?我需要允许用户对表中的数据行执行某些操作,但需要不刷新页面。

TIA,
本吉

4 个答案:

答案 0 :(得分:1)

我相信AHAH仅适用于drupal_get_form()。您必须自己编写AJAX(handbook page)。

也许您可以将drupal_get_form()的返回值保存在变量中并将其传递给主题函数?

答案 1 :(得分:1)

我认为这是一个错误,但我创建了一个非常简单的通用解决方案:) Januz的解决方案对我不起作用,因为该表已经在表单中使用,并且它仅适用于非常具体的用例而不是通用解决方案。 您可以查看以下代码和我编写的函数作为示例 注意:您可能需要修改代码以满足您的需求

/**
* @param $form
* @param $form_state
* @param $form_id
*/
function mymodule_form_alter(&$form, &$form_state, $form_id) {
    $test_button = array(
        'test_button' => array(
            '#type' => 'button',
            '#value' => t('Add'),
            '#name' => 'test_button',
            '#id' => 'test_button',
            '#weight' => 2,
            '#ajax' => array(
                'callback' => '_mymodule_ajax_callback',
            )
        )
    );
    $form['mytable'] = array(
        '#weight' => 1,
        '#theme' => 'table',
        '#header' => array(
            array("data" => "Item"),
        ),
        '#rows' => array(
            'data' => array(
                array(
                    'data' => $test_button
                ),
            )
        ),
    );
    // This is a work around, ajax elements do not work when used in drupal tables
    mymodule_table_ajax_workaround($test_button, $form, $form_state);
}


/**
 * Ajax enabled form elements do not work then used inside a drupal table and rendered via theme_table
 * This is a workaround to address the issue
 * @param $elements
 * @param $form
 * @param $form_state
 */
function mymodule_table_ajax_workaround($elements, &$form, &$form_state) {
    foreach ($elements as $element_name => $element_info) {
        drupal_add_js(array('ajax' => array(
            $element_name => array(
                'callback' => $element_info['#ajax']['callback'],
                'event' => 'mousedown',
                'keypress' => true,
                'prevent' => 'click',
                'url' => '/system/ajax',
                'submit' => array(
                    '_triggering_element_name' => $element_name . '_fake',
                    '_triggering_element_value' => $element_info['#value'],
                )
            ),
        )), 'setting');
        $form['form_ajax_workaround'][$element_name] = array(
            '#name' => $element_name . '_fake',
            '#input' => true,
            '#value' => $element_info['#value'],
            '#ajax' => array(
                'callback' => $element_info['#ajax']['callback']
            )
        );
    }
}

答案 2 :(得分:0)

您可以通过主题功能和表格生成来完成此操作。 AHAH会奏效。唯一的问题是当你有多个“桌子”时,事情开始变得毛茸茸。

答案 3 :(得分:0)

简短说明(如果我错了,请纠正我!):当Drupal的Form API保留在"#theme" => "table"渲染数组中时,启用AJAX的表单元素看起来是不可见的。这可能是由于render()使用element_children()而未查看表格的#header#rows元素。解决此问题的方法是向窗体中添加虚拟元素,这些元素对Form API可见,并将AJAX事件绑定到原始元素以触发虚拟元素。

我分享了新浪Salek对Drupal 7的强大解决方法,主要区别在于:

  1. 允许使用不同的表单字段键,名称和ID,
  2. JS AJAX设置对象的回调被删除,因为它似乎不存在于JS,
  3. 将基本路径变量添加到未安装在Web根目录中的网站的AJAX URL
  4. 使用"#type" => "value"表示虚拟按钮,而不是内部选项"#input" => TRUE
  5. 虚拟元素的名称与原始元素完全相同,没有“_fake”后缀,因为原始元素对于Form API是不可见的,虚拟元素不会出现在DOM中,
  6. 完整的#ajax数组被复制到虚拟元素而不仅仅是回调元素,因此其他设置(即针对throbber)仍然存在。
  7. 允许用户为每个按钮设置自定义JS AJAX选项。
  8. 构建表单时为每个启用AJAX的元素实现变通方法的示例:

    /**
     * My form.
     */
    function MY_MODULE_my_form($form, &$form_state) {
      // Define button. NB: An ID and name are required!
      $my_button = array(
        '#type' => 'button',
        '#id' => 'test_button',
        '#name' => 'test_button',
        '#value' => t('Button label'),
        '#ajax' => array('callback' => '_MY_MODULE_ajax_callback'),
      );
      // Call table AJAX workaround function on the button.
      MY_MODULE_table_ajax_workaround($my_button, $form);
    
      // Define table.
      $form['my_table'] = array(
        '#theme' => 'table',
        '#header' => array(
          array('data' => t('Column header')),
        ),
        '#rows' => array(
          'data' => array(
            array('data' => $my_button),
          )
        ),
      );
    
      return $form;
    }
    
    /**
     * Workaround for AJAX enabled form elements that remain inside tables.
     *
     * Problem: AJAX enabled form elements appear invisible to Drupal's Form API
     * when they remain inside a #theme => table render array. This is probably due
     * to render() using element_children() which does not look into a table's
     * #header or #rows elements.
     *
     * Workaround: Add dummy elements to the form which are visible to the Form API
     * and bind AJAX events to the original elements to trigger the dummy elements.
     *
     * Based on:
     * @link http://stackoverflow.com/questions/1981781
     *
     * Shared at:
     * @link http://stackoverflow.com/a/31098784/328272
     *
     * Another workaround is the render elements using custom theme functions, but
     * this seems slightly more complicated and rendered elements are no longer
     * alterable.
     * @link https://www.drupal.org/node/2101557#comment-7920151
     */
    function MY_MODULE_table_ajax_workaround($element, &$form, $js_ajax_options = array()) {
      // Add dummy element.
      $form['table_ajax_workaround'][$element['#id']] = array(
        '#type' => 'value',
        '#name' => $element['#name'],
        '#value' => $element['#value'],
        '#ajax' => $element['#ajax'],
      );
    
      // Bind AJAX event to the original element, default properties are used. See
      // Drupal.ajax in misc/ajax.js.
      $js_setting['ajax'][$element['#id']] = drupal_array_merge_deep(array(
        'event' => 'mousedown',
        'keypress' => true, // Use lowercase booleans to support IE.
        'prevent' => 'click',
        'url' => base_path() . 'system/ajax',
        'submit' => array(
          '_triggering_element_name' => $element['#name'],
          '_triggering_element_value' => $element['#value'],
        ),
      ), $js_ajax_options);
    
      // Add JS setting.
      drupal_add_js($js_setting, 'setting');
    }