AJAX forms will break when used in subform When using the following AJAX element in a BlockBase extended class everything seems to work just jolly good in the Block-layout page. 

$form['foobar_row']['add_more'] = [
  '#type' =&gt; 'submit',
  '#value' =&gt; $this-&gt;t('Add more'),
  '#submit' =&gt; [[$this, 'addOne']],
  '#ajax' =&gt; [
    'callback' =&gt; [$this, 'addmoreCallback'],
    'wrapper' =&gt; 'foobar-wrapper',
    'method' =&gt; 'replaceWith',
    'event' =&gt; 'click'
  ],
  '#id' =&gt; 'foobar__add_more'
];


Though, the block form will fail when used as a subform, in my case it's being used in a paragraph, which contains a block_field. And I can completely see why it's failing, since the $form in the callback method contains the entire node form. I even experimented with the following alteration to my callback method, which works, but is absolutely no solution since the entire path to the element should always be the same. 

  public function addmoreCallback(array &amp;$form, FormStateInterface $form_state) {
    $referral_field = $form_state-&gt;get('num_foobar_rows');

    // Note every parenting element being addressed in following, but I would ideally only have to define ['settings']['foobar_row'];
    return $form['field_paragraphs']['widget'][0]['subform']['field_paragraph_block_blocks']['widget'][0]['settings']['foobar_row'];
  }


How would I make my addmoreCallback more dynamic and make sure it returns the right element?
Use $form_state-&gt;getTriggeringElement()!  

Example for the callback:

public function addmoreCallback(array &amp;$form, FormStateInterface $form_state) {
    $items_field = $form_state-&gt;get('num_foobar_rows');

    // Gets the button that triggers the ajax call
    $triggering_element = $form_state-&gt;getTriggeringElement();

    // Retrieve the parents, so we can climb back up the tree and do not have to hard code the unknown position of our subform
    $parents = array_slice($triggering_element['#array_parents'], 0, -1);

    // Use NestedArray to get the element in `$form` at the path that `$parents` describes.
    return NestedArray::getValue($form, $parents);
}


Note that I'm using #array_parents, this will contain all the parents including simple array parents or elements without #tree. This will prevent problems you are most likely to encounter when your form gets embedded in a field and ofcourse other forms.

Also note that the array_slice part, this will just slice off some parents to make sure we have the path to our first (-1) parent. If the element that you want to return is one or more parents up the tree, you'll need to adjust the -1 accordingly. Also, if your to be returned element is not actually the parent of the triggering element you'll want to alter the $parents array accordingly.