How do I make an ajax callback in Field Plugin formElement() reload form?
Here is what I did in TVI which does something similar to what you are doing (changing out options):

    // form code ...

$form['tvi']['view'] = [
  '#type' =&gt; 'select',
  '#title' =&gt; 'Using the view',
  '#description' =&gt; $this-&gt;t('The default view that you want to use for all vocabularies and terms.'),
  '#default_value' =&gt; $config-&gt;get('view'),
  '#options' =&gt; $view_options,
  '#states' =&gt; [
    'visible' =&gt; [
      ':input[name="enable_override"]' =&gt; array('checked' =&gt; true),
    ]
  ],
  '#ajax' =&gt; [
    'callback' =&gt; '::loadDisplayOptions',
    'event' =&gt; 'change',
    'wrapper' =&gt; 'tvi-settings-wrapper',
    'progress' =&gt; array(
      'type' =&gt; 'throbber',
    ),
  ],
];

// form code ...

  /**
   * Ajax callback - null the value and return the form.
   * The value gets nulled because we cannot overwrite #default_value in an ajax callback.
   * @param array $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   * @return mixed
   * @see https://www.drupal.org/node/1446510
   * @see https://www.drupal.org/node/752056
   */
  public function loadDisplayOptions(array &amp;$form, FormStateInterface $form_state) {
    $form['tvi']['view_display']['#value'] = '';
    $form_state-&gt;setRebuild();
    return $form;
  }


In my form code, I am reading the values from $form_state and checking them - which is passed to a function that populates the option list. Therefore, when the AJAX callback rebuilds the form, the new option list will be populated.

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $values = $form_state-&gt;getValues();
    $config = $this-&gt;config('tvi.global_settings');
    $views = Views::getEnabledViews();

$view_options = ['' =&gt; ' - Select a View -'];
$display_options = ['' =&gt; ' - Select a View Display -'];
$default_display = '';

foreach ($views as $view) {
  $view_options[$view-&gt;id()] = $view-&gt;label();
}

if (isset($values['view'])) {
  $display_options += $this-&gt;getViewDisplayOptions($values['view']);
}
elseif ($config !== NULL) {
  $view = $config-&gt;get('view');
  $view_display = $config-&gt;get('view_display');

  if (isset($view)) {
    $display_options += $this-&gt;getViewDisplayOptions($view);
  }

  if (isset($view_display)) {
    $default_display = $view_display;
  }
}

$form['#prefix'] = '&lt;div id="tvi-settings-wrapper"&gt;';
$form['#suffix'] = '&lt;/div&gt;';

// irrelevant fields redacted...

$form['tvi']['view'] = [
  '#type' =&gt; 'select',
  '#title' =&gt; 'Using the view',
  '#description' =&gt; $this-&gt;t('The default view that you want to use for all vocabularies and terms.'),
  '#default_value' =&gt; $config-&gt;get('view'),
  '#options' =&gt; $view_options,
  '#states' =&gt; [
    'visible' =&gt; [
      ':input[name="enable_override"]' =&gt; array('checked' =&gt; true),
    ]
  ],
  '#ajax' =&gt; [
    'callback' =&gt; '::loadDisplayOptions',
    'event' =&gt; 'change',
    'wrapper' =&gt; 'tvi-settings-wrapper',
    'progress' =&gt; array(
      'type' =&gt; 'throbber',
    ),
  ],
];

$form['tvi']['view_display'] = [
  '#type' =&gt; 'select',
  '#title' =&gt; 'With this view display',
  '#description' =&gt; $this-&gt;t('The view display that you want to use from the selected view.'),
  '#default_value' =&gt; $default_display,
  '#options' =&gt; $display_options,
  '#states' =&gt; [
    'visible' =&gt; [
      ':input[name="enable_override"]' =&gt; array('checked' =&gt; true),
    ]
  ],
  '#prefix' =&gt; '&lt;div id="tvi-view-display"&gt;',
  '#suffix' =&gt; '&lt;/div&gt;',
];

return parent::buildForm($form, $form_state);
}


(Sorry for the broken paste) So when the form rebuilds, the options are populated from another method, while the AJAX callback just triggers a rebuild. 

As a side note, the reason I am setting #value to '' is to force the field to default to the placeholder 'Select a Value' on change. Otherwise, it will stick to the last selected position by the user.