Controlling a dependent field in a multi-instance paragraph The fields below are part of the node/add node/edit forms of my custom node type. 



The paragraph field_para_city contain one field_city. (I later need to add other fields in the paragraph).

The user can add multiple instances from field_para_city.

field_city has an allowed_values_function defined in a YML file, which returns all possible cities from all countries.

I created a class MyNodeTypeForm extends NodeForm, with a public function buildForm(). This function adds AJAX to field_country so that when it changes (i.e. the user chooses a country) it (re-)populates all the existing instances of field_city (inside the field_para_city instances) with corresponding list of cities (e.g., London and Cardiff for the UK).

In MY_MODULE.module, I added the following so that the above code is executed on the node/add and node/edit forms.

function MY_MODULE_entity_type_alter(array &amp;$entity_types) {
  $handlers = $entity_types['node']-&gt;get('handlers');
  $handlers['form']['default']  = 'Drupal\MY_MODULE\Form\MyNodeTypeForm';
  $handlers['form']['edit']     = 'Drupal\MY_MODULE\Form\MyNodeTypeForm';
  $entity_types['node']-&gt;set('handlers', $handlers);
}


All works fine, except when the user add or remove instances of field_para_city ("Add city" or "Remove"), then all instances of the field_para_city are refreshed and field_city instances inside them are reset to the allowed values (all cities), ignoring the state of field_country.

The user would then need to re-select from field_country to get the correct cities again.

I found that although adding/removing a field_para_city triggered the above mentioned buildForm() function, the $form_state-&gt;getValue('field_country') was then empty, unlike when buildForm() is triggered through the field_country AJAX.

I tried to capture the state of field_country in the field_city's allowed_values_function, so that the allowed options are dynamically and directly set based on the user choice of country, but $form_state was not recognised there.



I know this is an incorrect approach! 

What is the correct better approach to implement this simple use case?
I managed to make it work using a different approach; instead of overriding the NodeFrom, I used hook_field_widget_WIDGET_TYPE_form_alter and edited the subform array there.
Example:

/**
 * Implements hook_field_widget_WIDGET_TYPE_form_alter().
 */
function MY_MODULE_field_widget_entity_reference_paragraphs_form_alter(&amp;$element, \Drupal\Core\Form\FormStateInterface $form_state, $context)
{
  //Logic to exclude other Paragraph types
  if ($element['#paragraph_type'] !== 'YOUR_PARAGRAPH_TYPE'){ //e.g. cities
    return;
  }
  $element['subform']['field_places']['#states'] = [
    'visible' => [
      [
        //It worked for me with the ID of the select, I think you can use the name also
        '#edit-field-cities-0-subform-field-city' => array('value' => 'Cairo'),
      ]
    ]
  ];
}

When I add another paragraph, the ajax is fired and the selection is still preserved.
I haven't tried with other Ajax fields present though.