PAYATHON 2026

如何为 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 更新。

备注:内容仅供参考。