如何为 Drupal 地址字段的州/省选择框添加 AJAX?
结论
可以在地址字段 widget 的 administrative_area 元素上添加 #ajax,让 AJAX 回调返回需要更新的 County 区域。你提供的代码把 #after_build 挂在了 address 元素上,但回调收到的数组中,administrative_area 不一定就在这一层。另外,#attrributes 拼写有误,正确写法是 #attributes。Drupal 11 提供了 hook_field_widget_single_element_form_alter(),用于修改单个字段 widget 元素;它的参数包含 widget 元素和字段上下文。Drupal 11 Field Widget API
先确认元素路径
你给出的目标路径是:
$form['field_address']['widget'][0]['address']['administrative_area']
仅凭这段代码无法确定当前表单实际构建出的数组层级,也无法判断 County 是地址组件的一部分还是独立字段。可以先在 widget alter 中检查 $element,确认 address 和 administrative_area 是否存在,并找出 County 对应的表单键名。administrative_area 是否出现,也可能受所选国家和地址组件实际构建出的表单元素影响。
给州/省选择框添加 AJAX
如果检查确认 widget 元素中存在 $element['address']['administrative_area'],可以在字段 widget alter hook 中配置 AJAX。下面的代码沿用你提供的字段名和回调名:
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
function my_module_field_widget_single_element_form_alter(
array &$element,
FormStateInterface $form_state,
array $context
): void {
$field_name = $context['items']->getFieldDefinition()->getName();
if ($field_name !== 'field_address') {
return;
}
if (!isset($element['address']['administrative_area'])) {
return;
}
$element['address']['administrative_area']['#ajax'] = [
'callback' => 'address_us_county_update_county_callback',
'event' => 'change',
'wrapper' => 'field-b-county-wrapper',
];
}
这里的路径根据问题中给出的表单结构编写。如果检查后发现 administrative_area 位于其他层级,就按 $element 的实际结构调整。字段 widget alter hook 的用途和上下文参数见 Drupal 11 Field Widget API。
配置 County 更新区域和回调
wrapper 的值要与表单中实际存在的 HTML id 一致,AJAX 回调则要返回该区域对应的 render array。如果 County 是独立字段 field_county,可以按实际表单结构为它添加 wrapper:
$form['field_county']['#prefix'] = '<div id="field-b-county-wrapper">';
$form['field_county']['#suffix'] = '</div>';
function address_us_county_update_county_callback(
array &$form,
FormStateInterface $form_state
): array {
return $form['field_county'];
}
field_county 在这里仅作示例。如果 County 对应其他元素,需要把 wrapper 和回调中的路径改为实际路径,并确保回调返回包裹该 County 元素的区域。Drupal AJAX 回调接收 $form 和 $form_state,可以返回 render array 或 AJAX 命令。Drupal 11 Ajax API
检查原代码中的问题
#attrributes是拼写错误,正确属性名为#attributes。添加样式时可以写成$element['...']['#attributes']['style'] = 'background-color: #ffff00;',这样不会覆盖元素已有的其他属性。my_module_node_page_edit_form_alter()是否会执行,取决于 form ID 与 hook 名称是否匹配。先确认函数确实执行,再检查$after_build回调。如果 hook 名称不匹配,其中的 AJAX 设置就不会生效。- 如果
administrative_area不在当前元素路径下,isset()会跳过相关配置。调试时应检查实际 render array,确认元素的位置。 - 修改表单结构后,清理 Drupal 缓存,并检查浏览器开发者工具中的网络请求和响应,以判断问题出在事件绑定、回调执行还是目标 wrapper 更新。
备注:内容仅供参考。
