Dynamic dependent form select inputs I'm building a custom dependent dropdown form with 2 select inputs.

I've managed to build the form inputs and update them accordingly, but I'm not able to get the dependent select's value in the submit hook.

I think this happens because I changed (via AjaxResponse()/ReplaceCommand) the $form in the AJAX callback, and as such, the second input values aren't updated in the $form_state.

My problem is that I have no simple way of knowing which options will be available either in the first-level select nor in the dependent select, since they come from a 3rd-party API. 

Is there any way I can trigger the update of the #options in the dependent select, without having to render the nested dropdown and changing the $form so that the nested values are available in the submit hook?

Or, alternatively, is there anyway I can update the $form_state so that it knows the newly added #options of the second select?
With @4k4's help I managed to find the root cause of my issue and fix it.

I was wrongfully assuming that the $form elements could be somehow modified in an AJAX call to produce my desired effect.

While it is true that the elements could be modified and re-rendered in an AJAX response, that is not the correct way to alter a form after an AJAX call.

The 2 main things to know are:


forms are rebuilt everytime an AJAX call is made (when it is declared in the #ajax array of the form element triggering the call)
the AJAX function being called should (ideally) only return the element suffering modifications. It cannot modify the $form in any way, otherwise those modification will either be lost when it is rebuilt, or trigger the An illegal choice has been detected. Please contact the site administrator. message.


This being said, the general flow for this should be:


create the buildForm function with code that builds both your select elements. Wrap in a conditional clause code that tests if the parent select was already changed or not. This will be used to determine if the nested select should be populated or not;
set an #ajax property in the parent select element of the form, referring a callback to be used;
define the callback to return only the element which needs to change in the form, ie, the nested select;
when Drupal tries to rebuild the form, your parent select will already have a value that can be used in the above mentioned test-clause to allow for population of the nested callback.


@4k4's suggested documentation was difficult for me to find, but clear enough to follow trough once found - link here. (Even though it is for Drupal 7, in Drupal 8 it functioned exactly the same way).