坚果壳:
我试图通过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的键刷新C中的选项,因为C的键用于D的选项。
这些完全构建为Drupal AJAX回调,并且正常工作。但是,B不是选择,而是2个单独的文本字段,1个键,1个文字。我们这样做是为了能够对B进行AJAX自动完成查找,因为列表的大小太大而无法使用select元素。
我编写了一个外部jQuery脚本来执行此查找,并填充这两个字段(B_key和B_literal)。一旦我们填充它们,我们就会触发一个自定义事件,由字段'ajax'=>引用。 'event'=> 'hs_changed',我们在jQuery中使用jQuery('[name = b_literal]')手动触发。触发器()。这是我第一次这样做,导致C使用一组新选项重建。
然而,一旦发生这种情况,它就不再重建了。我找出了form_state,并注意到在为B选择一个新值时,表单状态认为已经单击了一个按钮(无论哪个是form_state ['buttons']数组中的第一个按钮),导致它失败。
现在,当我重新加载A时,它通常具有B的预设值,因此所有子字段(B,C,D,E)都会正确刷新。一旦发生这种情况,我可以再次手动选择B,如果我们再试一次,它会按照写入一次,然后失败。应该注意的是,我的jQuery没有绑定问题,因为它仍然能够找到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(第一次正确执行):
[triggering_element] =&gt;排列 ( [#type] =&gt;文本域 [#title] =&gt;乙 [#description] =&gt; [#default_value] =&gt; [#size] =&gt; 32 [#maxlength] =&gt; 255 [#required] =&gt; 1 [#disabled] =&gt; [#ajax] =&gt;排列 ( [callback] =&gt; b_ajax_callback [方法] =&gt;更换 [效果] =&gt;褪色 [event] =&gt; 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
)
答案 0 :(得分:2)
我认为当你使用jquery自动完成时会出现问题。而不是使用Drupal 7 Form API中给出的#autocomplete_path
,或者使用以下link它可以解决您的问题#autocomplete_path