I am working on some form api functionality in where there is an entity_autocomplete that populates based on a view. I am trying to attach some additional ajax/submit functionality to this so that once an entity is selected, it submits the ajax request/form to do some additional things. 

(For example, if a certain entity type is selected from the autocomplete, additional fields show up). #submit doesn't seem to work on entity_autocomplete, and you can't rebuild form_state (or set it) in the ajax callback, so I am trying to find another way to do what I need. 

This is what I have so far (Located inside of my BulkCheckoutForm.php class in my module)

If I add a dpm to the ajax callback 'test' it prints once the entity_autocomplete closes, but if I add anything to #submit it doesn't trigger, and I don't get any errors in watchdog.

$form['#id'] = 'bulk_checkout_form';

$form['items'][0]['search'] = [
  '#type' => 'entity_autocomplete',
  '#target_type' => 'item_type',
  '#selection_handler' => 'views',
  '#selection_settings' => [
    'view' => [
      'view_name' => 'main_records',
      'display_name' => 'entity_reference_1',
      'arguments' => [],
    ],
  'match_operator' => 'CONTAINS',
  ],
  '#ajax' => [
    'wrapper' => 'bulk_checkout_form',
    'callback' => '::test',
    'event' => 'autocompleteclose',
  ],
  '#submit' => ['::testSubmit'],
];
if ($form_state->get('showFormat')) {
  $form['items'][0]['format'] = [
    '#type' => 'select',
    '#title' => 'Format',
    '#options' => [],
  ];
}

function test(array &$form, FormStateInterface ($form_state) {
  return $form;
}

function testSubmit(array &$form, FormStateInterface $form_state) {
  $form_state->set('showFormat',TRUE);
  $form_state->setRebuild();
}

What I am trying to do is when an entity_autocomplete field has a value selected, it runs the `testSubmit` submit callback and sets showFormat to true (so that the form is rebuilt, and the format field is shown. #submit doesn't appear to trigger on entity_autocomplete though, and I can't set the $form_state inside of the ajax callback. 

Does anybody know what I can do to get the functionality I am trying to do?

Comments

wombatbuddy’s picture

Where is this code located, in the hook or in the form class? 
Did you set $form['#id'] = 'bulk_checkout_form' ?

jfurnas’s picture

Sorry for that incomplete bit. Yes, I do have $form['#id'] = 'bulk_checkout_form' set, and the ajax runs if I dpm, but the #submit doesn't run. 

It's directly in the build() method on the form class.

wombatbuddy’s picture

Try to get the value of the "$form['items'][0]['search']" element in build method instead, because Ajax callback runs later (after the build() method).

jfurnas’s picture

Using $form_state->getValue? That wouldn't be available until after the form is submitted would it? Since the field should only render when the autocomplete has a certain value, and thats not available until its provided, I don't know of a way to check the value, unless the autocomplete action submits the form and makes that fields value available. 

wombatbuddy’s picture

1. You have the typo in this code (extra parentheses): 

function test(array &$form, FormStateInterface ($form_state) {
  return $form;
}

2. Here is the working example, but I used my view that display users: 

  public function buildForm(array $form, FormStateInterface $form_state, NodeInterface $node = NULL) {
    $form['#id'] = 'bulk_checkout_form';

    $form['items'][0]['search'] = [
      '#type' => 'entity_autocomplete',
      '#target_type' => 'user',
      '#selection_handler' => 'views',
      '#selection_settings' => [
        'view' => [
          'view_name' => 'my_users',
          'display_name' => 'entity_reference_1',
          'arguments' => [],
        ],
        'match_operator' => 'CONTAINS',
      ],
      '#ajax' => [
        'wrapper' => 'bulk_checkout_form',
        'callback' => '::test',
        'event' => 'autocompleteclose',
      ],
    ];

    if ($form_state->getValue('search')) {
      $form['items'][0]['format'] = [
        '#type' => 'select',
        '#title' => 'Format',
        '#options' => [],
      ];
    }
    
    return $form;
  }

  /**
   * Custm Ajax handler.
   */
  function test(array &$form, FormStateInterface $form_state) {
    return $form;
  }
jfurnas’s picture

Okay, that appears to have worked. Now to adapt it to be repeatable using add another and 'remove'. At least that part is over and done with. 

Thank you!