Does an ajax callback work within a Views style plugin? My module has a custom Views style plugin. In the style settings form, I want to implement an ajax callback, such as described here: https://www.drupal.org/docs/8/api/javascript-api/ajax-forms

However, I haven't had any luck. I can get a spinning effect, but nothing happens afterward. Here's an example of what I've tried:

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;  

  public function TestCallback(array $form, FormStateInterface $form_state) {
    $ajax_response = new AjaxResponse();
    $text = 'Text to see if this is working';
    $ajax_response-&gt;addCommand(new HtmlCommand('#foo', $text));

    return $ajax_response;
  }

  /**
   * {@inheritdoc}
   */
  public function buildOptionsForm(&amp;$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);

    $form['test'] = [
      '#title' =&gt; t('TEST!'),
      '#type' =&gt; 'select',
      '#options' =&gt; [
        '' =&gt; t('None'),
        'foo' =&gt; t('Bar'),
      ],
      '#ajax' =&gt; [
        'event' =&gt; 'change',
        'callback' =&gt; '::TestCallback',
    // having the line below uncommented seems to help        
    //'url' =&gt; views_ui_build_form_url($form_state),
      ],
      '#prefix' =&gt; '&lt;div id="foo"&gt;&lt;/div&gt;',
      '#default_value' =&gt; '',
    ];
  }


If I uncomment the commented 'url', I get this error:

Uncaught TypeError: Cannot read property 'settings' of undefined
at resetSize (&lt;anonymous&gt;:34:32)
at later (debounce.js?v=8.6.3:20)


If I keep it commented, I get:

Failed to load resource: the server responded with a status of 500 () 
/admin/structure/views/ajax/display/view_name/page_1/style_options? 
_wrapper_format=drupal_ajax&amp;ajax_form=1&amp;_wrapper_format=drupal_ajax:1
Uncaught Drupal.AjaxError
ajax.js?v=8.6.3:500


What's missing and/or incorrect?
From what I understand seeing the AJAX docs, I think you're not supposed to return an AjaxResponse object. You're supposed to return a renderable array from the Ajax callback.

Sample Code

public function buildOptionsForm(&amp;$form, FormStateInterface $form_state) {
  parent::buildOptionsForm($form, $form_state);
  $form['test'] = [
    '#title' =&gt; t('TEST!'),
    '#type' =&gt; 'select',
    '#options' =&gt; [
      '' =&gt; t('None'),
      'foo' =&gt; t('Bar'),
    ],
    '#ajax' =&gt; [
      'event' =&gt; 'change',
      'wrapper' =&gt; 'ajax-output-container',
      // Since views style options forms are complex, they're built by
      // Drupal in a different way. To bypass this problem we need to
      // provide the full path to the Ajax callback.
      'callback' =&gt; __CLASS__ . '::testCallback',
    ],
    '#prefix' =&gt; '&lt;div id="ajax-output-container"&gt;&lt;/div&gt;',
    '#default_value' =&gt; '',
  ];
}

/**
 * This is the AJAX callback.
 *
 * It generates the output for the AJAX request. The output REPLACES
 * the "wrapper" you define in #ajax.
 */
public function testCallback(array $form, FormStateInterface $form_state) {
  // This element will replace the DIV#foo you have in your #prefix.
  $elem = [
    '#type' =&gt; 'markup',
    '#markup' =&gt; '&lt;div id="ajax-output-container"&gt;Is it not working!&gt;&lt;/div&gt;',
  ];
  return $elem;
}


Debugging


Make sure that on page load, you're getting a div with the correct ID in your field prefix. You can put some default text in the prefix so that you can see it on page load?
If HTML tags are being stripped from your #prefix markup for some reason, then try injecting a separate item in the form with #markup.