diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index 4d1dc27..71ec243 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -562,6 +562,18 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
     $unprocessed_form = $form;
     $form = $this->doBuildForm($form_id, $form, $form_state);
 
+    // Allow an Ajax callback while the form is operating in GET mode. For
+    // example, when using HOOK_form_views_exposed_form_alter.
+    if ($form_state->isMethodType('get')) {
+      $triggering_element_name = $this->requestStack->getCurrentRequest()->request->get('_triggering_element_name');
+      $triggering_element = $form_state->getTriggeringElement();
+      if (isset($triggering_element['#name'])
+        && $triggering_element['#name'] == $triggering_element_name
+        && isset($triggering_element['#ajax'])) {
+        throw new FormAjaxException($form, $form_state);
+      }
+    }
+
     // Only process the input if we have a correct form submission.
     if ($form_state->isProcessingInput()) {
       // Form values for programmed form submissions typically do not include a
diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php
index 9ee3704..0856696 100644
--- a/core/modules/views/src/ViewExecutable.php
+++ b/core/modules/views/src/ViewExecutable.php
@@ -689,7 +689,10 @@ class ViewExecutable {
       // Ensure that we can call the method at any point in time.
       $this->initDisplay();
 
-      $this->exposed_input = \Drupal::request()->query->all();
+      $request = \Drupal::request();
+      $triggered = $request->request->get('_triggering_element_name');
+      $this->exposed_input = $request->isMethod('post') && $triggered ? $request->request->all() : $request->query->all();
+
       // unset items that are definitely not our input:
       foreach (['page', 'q'] as $key) {
         if (isset($this->exposed_input[$key])) {
diff --git a/core/modules/views/tests/modules/views_test_exposed_filter/views_test_exposed_filter.info.yml b/core/modules/views/tests/modules/views_test_exposed_filter/views_test_exposed_filter.info.yml
new file mode 100644
index 0000000..2af2dcf
--- /dev/null
+++ b/core/modules/views/tests/modules/views_test_exposed_filter/views_test_exposed_filter.info.yml
@@ -0,0 +1,8 @@
+name: 'Views Test Exposed Filter'
+type: module
+description: 'Alters Views exposed filter form for testing AJAX callbacks.'
+package: Testing
+version: VERSION
+core: 8.x
+dependencies:
+  - drupal:views
diff --git a/core/modules/views/tests/modules/views_test_exposed_filter/views_test_exposed_filter.module b/core/modules/views/tests/modules/views_test_exposed_filter/views_test_exposed_filter.module
new file mode 100644
index 0000000..2c5065c
--- /dev/null
+++ b/core/modules/views/tests/modules/views_test_exposed_filter/views_test_exposed_filter.module
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Contains the "views_test_exposed_filter" module hooks and callbacks.
+ */
+
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function views_test_exposed_filter_form_views_exposed_form_alter(&$form, FormStateInterface $form_state) {
+  if (isset($form['title'])) {
+    $form['title']['#ajax']['callback'] = 'views_test_exposed_filter_ajax_callback';
+    $form['title']['#ajax']['wrapper'] = 'views-test-exposed-filter-test';
+    $form['title']['#prefix'] = '<span id="views-test-exposed-filter-test">Default prefix</span>';
+  }
+}
+
+/**
+ * Returns render array via an AJAX callback for testing.
+ *
+ * @param array $form
+ *   The form definition array.
+ * @param \Drupal\Core\Form\FormStateInterface $form_state
+ *   The form state object.
+ * @return array
+ *   Render array to display when the AJAX callback is triggered.
+ */
+function views_test_exposed_filter_ajax_callback(array &$form, FormStateInterface $form_state) {
+  return [
+    '#markup' => 'Callback called.',
+  ];
+}
diff --git a/core/modules/views/tests/src/FunctionalJavascript/ExposedFilterAJAXTest.php b/core/modules/views/tests/src/FunctionalJavascript/ExposedFilterAJAXTest.php
index 0fa1301..5bf62a3 100644
--- a/core/modules/views/tests/src/FunctionalJavascript/ExposedFilterAJAXTest.php
+++ b/core/modules/views/tests/src/FunctionalJavascript/ExposedFilterAJAXTest.php
@@ -5,6 +5,7 @@ namespace Drupal\Tests\views\FunctionalJavascript;
 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
 use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
 use Drupal\Tests\node\Traits\NodeCreationTrait;
+use Drupal\views\Tests\ViewTestData;
 
 /**
  * Tests the basic AJAX functionality of Views exposed forms.
@@ -19,7 +20,13 @@ class ExposedFilterAJAXTest extends WebDriverTestBase {
   /**
    * {@inheritdoc}
    */
-  public static $modules = ['node', 'views', 'views_test_modal'];
+  public static $modules = ['node', 'views', 'views_test_modal', 'views_test_config'];
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $testViews = ['test_content_ajax'];
+
 
   /**
    * {@inheritdoc}
@@ -151,4 +158,27 @@ class ExposedFilterAJAXTest extends WebDriverTestBase {
     $this->assertNotContains('Page Two', $html);
   }
 
+  /**
+   * Tests if AJAX events can be attached to the exposed filter form.
+   */
+  public function testExposedFilterAjaxCallback() {
+    ViewTestData::createTestViews(self::class, ['views_test_config']);
+
+    // Attach an AJAX event to all 'title' fields in the exposed filter form.
+    \Drupal::service('module_installer')->install(['views_test_exposed_filter']);
+    $this->resetAll();
+    $this->rebuildContainer();
+    $this->container->get('module_handler')->reload();
+
+    $this->drupalGet('test-content-ajax');
+
+    $page = $this->getSession()->getPage();
+    $this->assertSession()->pageTextContains('Default prefix');
+
+    $page->fillField('title', 'value');
+    $this->assertSession()->assertWaitOnAjaxRequest();
+
+    $this->assertSession()->pageTextContains('Callback called.');
+  }
+
 }