I'm porting a module that currently works with Blocks/BlockForms to Paragraphs/NodeForms. I'm inserting an embedded form inside a Paragraph inside a Node Edit page using a hook_field_widget_entity_reference_paragraphs_form_alter. The general structure where the form gets inserted is:

$form['field']['widget'][0]['settings'][form here]

After this the form displays as expected on the node edit page.

The inserted form goes through a number of #process steps. The element in question is a select form that when the button underneath it is pressed, is supposed to retrieve some data via a custom submit handler and place it on the page with ajax:

enter image description here

The array for this element looks like this:

enter image description here

You can see the custom submit handler that is supposed to fire when 'Select Segment Set' is pressed

After debugging, I've found that the entire NodeForm appears to be submitted to the backend, and the only handler that is found is from some other field that uses ajax. In short 'updateSegmentSet' is never discovered as a submit handler. When I debug the original module based on block/blockforms, I do see the correct submit handler being discovered. Now in the latter case, of course a blockForm is submitted to the back end with the correct plugin. Given that this is basically a form within a form within a form, is there something special I have to do to get the custom submit handler to run? I've read a few things online e.g. the 'settings' key and '#tree' = true.


The Ajax property looks like this:

      '#ajax' => [
        'callback' => [$this, 'updateSegmentSetAjax'],
        'wrapper' => $wrapper_id,

  public function updateSegmentSetAjax(array &$form, FormStateInterface $form_state) {
    $button = $form_state->getTriggeringElement();
    // Go one level up in the form, to the widgets container.
    return NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -2));

As best I can tell, this is never called either.

  • What are you doing in the #ajax property? Maybe this does interfere with your submit callback. Commented Feb 13, 2021 at 10:37
  • I edited the question to include the #ajax code
    – plambre
    Commented Feb 13, 2021 at 16:02
  • Try '::ajaxCallback` to call class methods. This expands automatically to the current form object.
    – 4uk4
    Commented Feb 13, 2021 at 17:38
  • Just want to verify you mean '#ajax' => ['callback' => [$this, '::updateSegmentSetAjax']] and not '#ajax' => ['callback' => ['::updateSegmentSetAjax]]
    – plambre
    Commented Feb 13, 2021 at 18:24
  • 'callback' => '::ajaxCallback',
    – 4uk4
    Commented Feb 13, 2021 at 19:19

1 Answer 1


I came across https://www.drupal.org/forum/support/module-development-and-code-questions/2015-09-03/put-a-custom-form-inside-node-form which, while old, claims that what I wanted to do is not possible. To get this to function the way I wanted I:

  • Attached a JS event handler to the embedded form submit buttons that performed .preventDefault()
  • This handler then .ajax'd a custom route that I created.
  • In the Controller for that route, I had to perform all the primary operations for submitting the form and return markup back to the .ajax call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.