How do I change the default value of a field with AJAX? Related to my previous question: Form fields created via Ajax are missing element attributes

I have a date field and a series of text and number fields which need their default values to change based on the value of the date field. I've updated my code so it functions this way:

public function buildForm(array $form, FormStateInterface $form_state) {
    $form['date'] = array(
        '#type' =&gt; 'date',
        '#ajax' =&gt; [
            'callback' =&gt; '::dateCallback',
            'wrapper' =&gt; 'wrapper',
        ],
        '#default_value' =&gt; date("Y-m-d")
    );
    $form['wrapper'] = [
        '#type' =&gt; 'container',
        '#attributes' =&gt; ['id' =&gt; 'wrapper'],
    ];

    //insert logic to determine value of a variable called $field1    
    $form['wrapper']['options'] = array(
        '#type' =&gt; 'fieldset',
        '#attributes' =&gt; array('class' =&gt; array('options'))
    );
    $form['wrapper']['options']['field1'] = array(
        '#type' =&gt; 'textfield',
        '#title' =&gt; "Field 1",
        '#value' =&gt; $field1
    );
    $form['wrapper']['table'] = array(
        '#type' =&gt; 'table',
        '#title' =&gt; t('Table'),
        '#header' =&gt; array("H1", "H2", "H3"),
        '#attributes' =&gt; array('class' =&gt; array('custom-table'))
    );
    //insert logic to generate table rows
    return $form;
}

/**
 * Implements callback for Ajax event on date selection.
 *
 * @param array $form
 *   From render array.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   Current state of form.
 *
 * @return array
 *   Date selection section of the form.
 */
public function dateCallback(array &amp;$form, FormStateInterface $form_state) {
    return $form['wrapper'];
}


There are 2 problems I am having with this:

1) Implementing it in this way, such that the #value property is changed when the date field is changed, technically works, however if the user then chooses to modify any of the textfield values, that is not reflected in the $form_state object and is overridden by whatever #value was last set to in buildForm().

2) I have also tried using #default_value instead, but the value in the field will not update if it already has something in it (which it usually does from the first time #default_value is set in buildForm()). I have seen some threads like this one suggesting to unset the value in $form_state before setting #default_value again, however all such suggestions are for Drupal 7 where $form_state is a completely different data structure.

Is there a known way to do what I am trying to accomplish?

Update: I tried method 2 again by adding $form_state-&gt;unsetValue('field1'); before declaring $form['wrapper']['options']['field1'], but this did not change the behaviour.
Method 1 setting #value does indeed make it impossible for the user to input data.

So the method 2 setting #default_value is I think still the best approach. As the old trick from D7, unsetting the value in $form_state, doesn't work anymore, you can try this one:

Create the field in a subkey, which is incremented for each request. Set the property #tree on the first level of the field, so you get back the field value as array [$key =&gt; $value]:

$form['wrapper']['options']['field1']['#tree'] = TRUE;

if ($form_state-&gt;hasValue('field1')) {
  $key = key($form_state-&gt;getValue('field1'));
  $value_field1 = current($form_state-&gt;getValue('field1')); 
  $key++;
}
else {
  $key = '0';
  $value_field1 = NULL;
}

// insert logic to determine new field value
// but check, if there is user input in $value_field1, that you don't want to overwrite

$form['wrapper']['options']['field1'][$key] = [
  '#type' =&gt; 'textfield',
  '#title' =&gt; 'Text 1',
  '#default_value' =&gt; $value_field1,
];