jquery - Drupal 7 : Triggering an AJAX callback externally in the Form API

标签 jquery ajax drupal drupal-7 form-api

简而言之:

我试图通过 jQuery 触发外部事件,从而导致在 Drupal 表单上执行 AJAX 回调。这会重建几个链接元素。它可以工作一次,但随后就会中断,直到表单被 Drupal 中的不同元素刷新为止。

form_state 在第一次尝试时检测到正确的元素作为触发元素,但之后默认为 form_state['buttons'] 数组中的第一个可用按钮。有什么想法吗?

详细信息:

我有一个复杂的 Drupal 表单,如下所示:

A(下拉菜单)

B(实际上是B_key和B_literal,2个文本字段) C(下拉菜单) D(下拉菜单) E(下拉菜单)

其中 A 刷新 B、B 刷新 C、C 刷新 D,依此类推。除了 B 之外,这些都是下拉元素。每个项目都是一个键=>值对,我们使用键来重建它刷新的元素中的选项。因此,B 的 key 会刷新 C 中的选项,因为 C 的 key 用于 D 的选项。

这些完全是作为 Drupal AJAX 回调构建的,并且可以正常工作。然而,B 不是一个选择,而是 2 个独立的文本字段,1 个键,1 个文字。我们这样做是为了对 B 进行 AJAX 自动完成查找,因为列表太大而无法使用选择元素。

我编写了一个外部 jQuery 脚本来执行此查找,并填充这两个字段(B_key 和 B_literal)。一旦我们填充它们,我们就会触发一个自定义事件,由字段的 'ajax' => 'event' => 'hs_changed' 引用,我们在 jQuery 中使用 jQuery('[name=b_literal]').trigger 手动触发该事件()。这是我第一次执行此操作时有效的,导致 C 使用一组新选项进行重建。

但是,一旦发生一次,就不再重建。我跟踪了 form_state,并注意到当为 B 选择新值时,表单状态认为已单击了一个按钮(以 form_state['buttons'] 数组中的第一个按钮为准),导致此操作失败。

现在,当我重新加载 A 时,B 通常会有一个预设值,因此所有子字段(B、C、D、E)都会正确刷新。一旦发生这种情况,我可以再次手动选择 B,并且它会像写一次一样工作,如果我们重试就会失败。应该注意的是,我的 jQuery 没有绑定(bind)问题,因为它仍然能够找到 B 的字段并更新值。它手动触发自定义事件(以触发 drupal 字段的 ajax),每次触发后都会失败。

这是我们的代码:

形式:

$form['a'] = array (
  '#type' => 'select',
  '#options' => $a_options,
  '#default_value' => $a_selected,
  '#required' => TRUE,
  '#prefix' => '<div id="a_wrapper">',
  '#suffix' => '</div>',
  '#ajax' => array(
    'callback' => 'a_ajax_callback',
    'method' => 'replace',
    'effect' => 'fade',
  ),
);

$form['b_key'] = array (
  '#type' => 'textfield',
  '#default_value' => $hierarchy['b_key'],
);

$form['b_literal'] = array (
  '#type' => 'textfield',
  '#default_value' => $hierarchy['b_literal'],
  '#size' => 32,
  '#required' => TRUE,
  '#ajax' => array(
    'callback' => 'b_ajax_callback',
    'method' => 'replace',
    'effect' => 'fade',
    'event' => 'hs_changed',
  ),
  '#prefix' => '<div id="b_wrapper">',
  '#suffix' => '</div>',
);

$form['c'] = array (
  '#type' => 'select',
  '#default_value' => $hierarchy['c'],
  '#empty_option' => '- Select -',
  '#options' => get_children_options_array($hierarchy['b_key'], TRUE),
  '#ajax' => array(
    'callback' => 'c_ajax_callback',
    'method' => 'replace',
    'effect' => 'fade',
  ),
  '#required' => TRUE,
  '#prefix' => '<div id="c_wrapper">',
  '#suffix' => '</div>',
);

//Assume D and E are identical to C

回调:

 function a_ajax_callback($form, &$form_state) {

   //Return the field to be rebuilt by the AJAX request  $commands = array();
   $commands[] = ajax_command_replace("#b_key_wrapper", render($form['b_key']));
   $commands[] = ajax_command_replace("#b_literal_wrapper", render($form['b_literal']));

   //We also unset a bunch of form_state['input'] values and such here

   return array('#type' => 'ajax', '#commands' => $commands);
 }

 //The b_ajax_callback and c_ajax_callback are pretty much identical

jQuery:

jQuery(document).on("focus", '[name=my_search]:not(.ui-autocomplete-input)', function() { 
  jQuery(this).autocomplete({
    source: function(req, res) {
      ch_search(req, res);
    },
    minLength: 3,
    select: function(event, ui) {
      ch_render_dropdowns(ui.item.id);
    }
  }); 
});

function ch_render_dropdowns(ch_node) {

  var token = jQuery('[name=ajax_token]').val();

  jQuery.ajax({
    url: '/ajax/myFunction/' + ch_node
    async: false,
    cache: false,
    data: {
      'token': token
    },
    success: function(data) {

      jQuery('#autoComplete_logic').html(data);
      jQuery('#autoComplete_logic').hide();

      // Once we have the initial results, fill in the d7 form fields
      // where we have values.
      var b_key = jQuery("#b_key").val();
      var b_name = jQuery("#b_literal").text();

      // Set our Drupal B Fields
      jQuery('[name=b_key]').val(b_key);
      jQuery('[name=b_literal]').val(b_name);

      //Trigger the refresh of all submenus in Drupal
      //This triggers the AJAX callback attached to the b_literal 
      //to rebuild c, d, and e.
      jQuery('[name=b]').trigger('hs_changed');
    }
  });
}

我已经简化了一切,因为有很多逻辑超出了这个问题的范围。自动完成不是问题。触发 b_literal 字段附加的 Drupal AJAX 激活,导致 c、d 和 e 的刷新,在第一次之后不起作用,除非我们点击字段 a,它通过 Drupal 的 Form API 在内部刷新 b、c、d 和 e AJAX 逻辑。

Form_state(第一次正确执行):

[触发元素] => 数组 ( [#type] => 文本字段 [#title] => B [#描述] => [#默认值] => [#尺寸] => 32 [#最大长度] => 255 [#必需] => 1 [#禁用] => [#ajax] => 数组 ( [回调] => b_ajax_callback [方法] => 替换 [效果] => 淡出 [事件] => hs_changed )

        [#prefix] => <div id="b_literal_wrapper">
        [#suffix] => </div>
        [#input] => 1
        [#autocomplete_path] => 
        [#process] => Array
            (
                [0] => ajax_process_form
            )

        [#theme] => textfield
        [#theme_wrappers] => Array
            (
                [0] => form_element
            )

        [#pre_render] => Array
            (
                [0] => ctools_dependent_pre_render
            )

        [#defaults_loaded] => 1
        [#tree] => 
        [#parents] => Array
            (
                [0] => b
            )

        [#array_parents] => Array
            (
                [0] => b
            )

        [#weight] => 0.002
        [#processed] => 
        [#attributes] => Array
            (
            )

        [#title_display] => before
        [#id] => edit-b--4
        [#name] => b_literal
        [#value] => 
        [#needs_validation] => 1
    )

Form_state(第二次执行不正确,之后每次执行):

[triggering_element] => Array
    (
        [#type] => submit
        [#value] => Submit
        [#weight] => 100
        [#attributes] => Array
            (
                [class] => Array
                    (
                        [0] => btn
                        [1] => btn-primary
                    )

            )

        [#after_build] => Array
            (
                [0] => _load_assets_b_select
            )

        [#input] => 1
        [#name] => op
        [#button_type] => submit
        [#executes_submit_callback] => 1
        [#limit_validation_errors] => 
        [#process] => Array
            (
                [0] => ajax_process_form
            )

        [#theme_wrappers] => Array
            (
                [0] => button
            )

        [#defaults_loaded] => 1
        [#tree] => 
        [#parents] => Array
            (
                [0] => submit
            )

        [#array_parents] => Array
            (
                [0] => submit
            )

        [#processed] => 
        [#required] => 
        [#title_display] => before
        [#id] => edit-submit--2
    )

[clicked_button] => Array
    (
        [#type] => submit
        [#value] => Submit
        [#suffix] => </div></section>
        [#weight] => 100
        [#attributes] => Array
            (
                [class] => Array
                    (
                        [0] => btn
                        [1] => btn-primary
                    )

            )

        [#after_build] => Array
            (
                [0] => _load_assets_b_select
            )

        [#input] => 1
        [#name] => op
        [#button_type] => submit
        [#executes_submit_callback] => 1
        [#limit_validation_errors] => 
        [#process] => Array
            (
                [0] => ajax_process_form
            )

        [#theme_wrappers] => Array
            (
                [0] => button
            )

        [#defaults_loaded] => 1
        [#tree] => 
        [#parents] => Array
            (
                [0] => submit
            )

        [#array_parents] => Array
            (
                [0] => submit
            )

        [#processed] => 
        [#required] => 
        [#title_display] => before
        [#id] => edit-submit--2
    )

最佳答案

我认为当您使用 jquery 自动完成时存在问题。相反,请使用 Drupal 7 Form API 中给出的 #autocomplete_path ,或使用以下 link它可能会解决您的问题#autocomplete_path

关于jquery - Drupal 7 : Triggering an AJAX callback externally in the Form API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12375542/

相关文章:

jquery - 如何使用 JQuery 克隆没有事件的数据元素

javascript - Angular JS - $q.all() 跟踪个人上传进度

javascript - Ajax 发送 FormData 并检索多维数组

php - 如何在jquery中像克隆一样创建查询mysql

javascript - Bootstrap 模态未启动

jquery - ASP.NET JSON WCF 服务截断响应

javascript - 使 YUI TreeView 仅使用 +/- 图标展开/折叠

php - 在 drupal 中使用 hook_form_alter 设置 webform 组件值

css - Drupal 模块填充取决于背景颜色

drupal - 我应该选择哪个版本的 Drupal?