简体   繁体   中英

Ajax and hook_form_alter

I'm getting a " The value you selected is not a valid choice. " error for an Ajax modified field when I submit a custom altered node/add form. An "Illegal choice error is also written to the log. This a Drupal 9 version of an app that I developed using Drupal 7 which worked. The Ajax functionality is working. Why? How do I fix it?

I believe the error is coming from some Symfony code. I'm dynamically modifying two "select" form elements. The first doesn't appear to have the problem. I'm doing the same thing for both form elements.

    function bncreports_form_node_bnc_message_form_alter(&$form, FormStateInterface $form_state, $form_id)
{
  $form['actions']['submit']['#submit'][]  = 'bncreports_node_bnc_message_form_submit';
  $form['#title'] = t('Create Contact Us');

  $user = User::load(\Drupal::currentUser()->id());
  $district_id = $user->get('field_district')->value;

  $form['field_first_name']['widget'][0]['value']['#default_value'] = $user->get('field_first_name')->value;
  $form['field_last_name']['widget'][0]['value']['#default_value'] = $user->get('field_last_name')->value;
  $form['field_email']['widget'][0]['value']['#default_value'] = $user->getEmail();
  $form['field_email']['widget'][0]['value']['#attributes'] = ['onblur' => 'this.value=this.value.toLowerCase();'];
  $form['field_phone']['widget'][0]['value']['#default_value'] = $user->get('field_phone')->value;
  $form['field_district']['widget'][0]['value']['#default_value'] = $district_id;
  if (isset($form['field_district']['widget']['#default_value']))
    $form['field_district']['widget']['#default_value'] = $district_id; // wtf?

  if ($user->hasRole('administrator') || $user->hasRole('bnc_operator') || $user->hasRole('ao_user')) {
    $form['field_office']['#access'] = false;
    $form['field_office_name']['#access'] = false;
    $form['field_office_names']['#access'] = false;
    $form['field_site_codes']['#access'] = false;
    $form['field_district']['widget']['#ajax'] = [
      'event' => 'change',
      'callback' => 'bncreports_ajax_offices_and_user',
      'wrapper' => ['ajax-wrapper-field-offices', 'ajax-wrapper-field-user'],
    ];
    $form['field_offices']['#prefix'] = '<div id="ajax-wrapper-field-offices">';
    $form['field_offices']['#suffix'] = '</div>';
    $form['field_user']['#prefix'] = '<div id="ajax-wrapper-field-user">';
    $form['field_user']['#suffix'] = '</div>';

    $district_id = $form_state->hasValue('field_district')
      ? $form_state->getValue('field_district')[0]['value']
      : false;

    $form['field_offices']['widget']['#options'] = $district_id
      ? Functions::officeNames($district_id)
      : [];

    $form['field_user']['widget']['#options'] = $district_id
      ? ['_none' => '- Select a value -'] + Functions::districtUserLastandFirstNames($district_id)
      : ['_none' => '- Select a value -'];
  } else { // Alterations for court users only
    $form['bnc_prefix']['#markup'] =
      '<p>BNC User Support: ' . Constants::BNC_PHONE_NO
      . ' <a href="mailto:' . Constants::BNC_EMAIL . '">' . Constants::BNC_EMAIL . '</a></p>'
      . '<p><a href="' . Constants::AO_CONTACTS_URL . '">AO Program and CM/ECF Contacts</a></p>'
      . '<h4>Unable to find what you need? Send us a message.</h4>';
    $form['bnc_prefix']['#weight'] = -1;

    $form['field_offices']['#access'] = false;
    $form['field_office_name']['#access'] = false;
    $form['field_office_names']['#access'] = false;
    $form['field_site_codes']['#access'] = false;
    $form['field_user']['#access'] = false;
    $form['field_non_user_name']['#access'] = false;
    $form['field_non_user_phone']['#access'] = false;
    $form['field_assigned_to']['#access'] = false;
    $form['revision_information']['#access'] = false;

    $office = $user->get('field_office')->value;
    $form['field_district']['widget']['#default_value'] = $district_id;
    $form['field_office']['widget']['#options'] = Functions::officeNames($district_id);
    $form['field_office']['widget']['#default_value'] = $office;
    $form['field_office_name']['widget'][0]['value']['#default_value'] = Functions::officeName($district_id, $office);

    $form['#attached']['library'][] = 'bncreports/restricted_contact_log';
  }
}

    function bncreports_ajax_offices_and_user(array $form, FormStateInterface $form_state): AjaxResponse
{
  $response = new AjaxResponse();
  // Issue a command that replaces the elements 'field_offices' and 'field_user'

  $response->addCommand(new ReplaceCommand('#ajax-wrapper-field-office', $form['field_offices']));
  $response->addCommand(new ReplaceCommand('#ajax-wrapper-field-user', $form['field_user']));

  return $response;
}

Problem is there are no allowed values for the field_user list. Solution is to use an allowed values function callback. This is done in Configuration synchronization for Field Storage. Set the allowed value function property and import. Need to provide uuid to override existing config.

In my hook_form_alter:

$_SESSION['selected_district_id'] = $district_id;

In my xxx.module:

function bncreports_allowed_values_function(FieldStorageConfig $definition, ContentEntityInterface $entity = NULL, $cacheable): array
{
  // NOTE: This is defined in Configuation synchronization for Field Storage (see node.field_user)
  if ($entity->bundle() == 'bnc_message') { // Add a custom field_user options for BNC Message nodes.
    $district_id = $_SESSION['selected_district_id'] ?? null;
    return Functions::districtUserLastandFirstNames($district_id);
  }

  throw new Exception("Allowed values function for {$entity->bundle()} is not allowed.");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM