diff --git a/core/modules/views/src/Plugin/views/filter/Date.php b/core/modules/views/src/Plugin/views/filter/Date.php
index 52dabbe..65c4cdd 100644
--- a/core/modules/views/src/Plugin/views/filter/Date.php
+++ b/core/modules/views/src/Plugin/views/filter/Date.php
@@ -142,7 +142,7 @@ public function acceptExposedInput($input) {
     // Don't filter if value(s) are empty.
     $operators = $this->operators();
     if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id'])) {
-      $operator = $input[$this->options['expose']['operator_id']];
+      $operator = $input[$this->options['expose']['identifier']]['operator'];
     }
     else {
       $operator = $this->operator;
diff --git a/core/modules/views/src/Plugin/views/filter/NumericFilter.php b/core/modules/views/src/Plugin/views/filter/NumericFilter.php
index af30472..d0aa823 100644
--- a/core/modules/views/src/Plugin/views/filter/NumericFilter.php
+++ b/core/modules/views/src/Plugin/views/filter/NumericFilter.php
@@ -139,18 +139,29 @@ protected function operatorValues($values = 1) {
    * Provide a simple textfield for equality
    */
   protected function valueForm(&$form, FormStateInterface $form_state) {
-    $form['value']['#tree'] = TRUE;
+    // Set a filter wrapper.
+    $exposed = !empty($this->options['expose']);
+    $wrapped = ($exposed && in_array($this->operator, $this->operatorValues(2))) || !empty($this->options['expose']['use_operator']);
+    if ($wrapped) {
+      $form['value']['#type'] = 'fieldset';
+      if (!empty($this->exposedInfo()['label'])) {
+        $form['value']['#title'] = $this->exposedInfo()['label'];
+      }
+      if (!empty($this->exposedInfo()['description'])) {
+        $form['value']['#description'] = $this->exposedInfo()['description'];
+      }
+      if ($exposed) {
+        $form['value']['operator'] = $form[$this->options['expose']['operator_id']];
+        unset($form[$this->options['expose']['operator_id']]);
+      }
+    }
 
     // We have to make some choices when creating this as an exposed
     // filter form. For example, if the operator is locked and thus
     // not rendered, we can't render dependencies; instead we only
     // render the form items we need.
     $which = 'all';
-    if (!empty($form['operator'])) {
-      $source = ':input[name="options[operator]"]';
-    }
-
-    if ($exposed = $form_state->get('exposed')) {
+    if ($exposed) {
       $identifier = $this->options['expose']['identifier'];
 
       if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) {
@@ -158,13 +169,17 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
         $which = in_array($this->operator, $this->operatorValues(2)) ? 'minmax' : 'value';
       }
       else {
-        $source = ':input[name="' . $this->options['expose']['operator_id'] . '"]';
+        $source = ':input[name="' . $this->options['expose']['identifier'] . '[operator]"]';
       }
     }
+    // Need to adjust the states source for the filter admin form.
+    if (!empty($form['operator'])) {
+      $source = ':input[name="options[operator]"]';
+    }
 
     $user_input = $form_state->getUserInput();
     if ($which == 'all') {
-      $form['value']['value'] = array(
+      $value['value'] = array(
         '#type' => 'textfield',
         '#title' => !$exposed ? $this->t('Value') : '',
         '#size' => 30,
@@ -172,7 +187,7 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
       );
       // Setup #states for all operators with one value.
       foreach ($this->operatorValues(1) as $operator) {
-        $form['value']['value']['#states']['visible'][] = array(
+        $value['value']['#states']['visible'][] = array(
           $source => array('value' => $operator),
         );
       }
@@ -184,7 +199,7 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
     elseif ($which == 'value') {
       // When exposed we drop the value-value and just do value if
       // the operator is locked.
-      $form['value'] = array(
+      $value = array(
         '#type' => 'textfield',
         '#title' => !$exposed ? $this->t('Value') : '',
         '#size' => 30,
@@ -197,16 +212,15 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
     }
 
     if ($which == 'all' || $which == 'minmax') {
-      $form['value']['min'] = array(
+      $value['min'] = array(
         '#type' => 'textfield',
-        '#title' => !$exposed ? $this->t('Min') : $this->exposedInfo()['label'],
+        '#title' => $exposed ? $this->t('Min') : '',
         '#size' => 30,
         '#default_value' => $this->value['min'],
-        '#description' => !$exposed ? '' : $this->exposedInfo()['description']
       );
-      $form['value']['max'] = array(
+      $value['max'] = array(
         '#type' => 'textfield',
-        '#title' => !$exposed ? $this->t('And max') : $this->t('And'),
+        '#title' => $exposed ? $this->t('And max') : $this->t('And'),
         '#size' => 30,
         '#default_value' => $this->value['max'],
       );
@@ -218,9 +232,10 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
             $source => array('value' => $operator),
           );
         }
-        $form['value']['min'] += $states;
-        $form['value']['max'] += $states;
+        $value['min'] += $states;
+        $value['max'] += $states;
       }
+
       if ($exposed && !isset($user_input[$identifier]['min'])) {
         $user_input[$identifier]['min'] = $this->value['min'];
       }
@@ -228,14 +243,16 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
         $user_input[$identifier]['max'] = $this->value['max'];
       }
 
-      if (!isset($form['value'])) {
+      if (!isset($value)) {
         // Ensure there is something in the 'value'.
-        $form['value'] = array(
+        $value = array(
           '#type' => 'value',
           '#value' => NULL
         );
       }
     }
+    $form['value'] += $value;
+    $form['value']['value']['#tree' = TRUE;
   }
 
   public function query() {
diff --git a/core/modules/views_ui/src/Tests/FilterNumericWebTest.php b/core/modules/views_ui/src/Tests/FilterNumericWebTest.php
index f891995..2b0700e 100644
--- a/core/modules/views_ui/src/Tests/FilterNumericWebTest.php
+++ b/core/modules/views_ui/src/Tests/FilterNumericWebTest.php
@@ -112,6 +112,80 @@ public function testFilterNumericUI() {
     $this->assertRaw('<label for="edit-age-min">Age between</label>', 'Min field label found');
     // Check that the description is shown in the right place.
     $this->assertEqual(trim($this->cssSelect('.form-item-age-min .description')[0]), 'Description of the exposed filter');
+
+    // Test if label and description are still visible if you have more than one
+    // exposed filter form element (select and one input, select and two inputs,
+    // or two inputs.
+    $label = 'Age filter';
+    $label_not_found = 'Label not found on other form item.';
+    $description = 'Age filter description';
+    $description_not_found = 'Description not found on (other) form item';
+
+    // Prepare view with numeric filter.
+    $this->drupalGet('admin/structure/views/nojs/handler/test_view/default/filter/age');
+
+    // Test the selector and value, min and max fields have the correct label
+    // and no description when viewed in the settings UI.
+    $this->assertEqual(trim($this->cssSelect('#edit-options-operator--wrapper .fieldset-legend')[0]), 'Operator');
+    // When the isNull and notIsNull options are available the total number of
+    // options > 10, so they get rendered as a select.
+    //$this->assertEqual(trim($this->cssSelect('.form-item-options-operator label')[0]), 'Operator');
+    $this->assertEqual(count($this->cssSelect('.form-item-options-operator description')), 0, $description_not_found);
+    $this->assertEqual(trim($this->cssSelect('.form-item-options-value-value label')[0]), 'Value');
+    $this->assertEqual(count($this->cssSelect('.form-item-options-value-value description')), 0, $description_not_found);
+    $this->assertEqual(trim($this->cssSelect('.form-item-options-value-min label')[0]), 'Min');
+    $this->assertEqual(count($this->cssSelect('.form-item-options-value-min description')), 0, $description_not_found);
+    $this->assertEqual(trim($this->cssSelect('.form-item-options-value-max label')[0]), 'And max');
+    $this->assertEqual(count($this->cssSelect('.form-item-options-value-max description')), 0, $description_not_found);
+
+    // First try two inputs, no select.
+    $edit = array();
+    $edit['options[expose][label]'] = $label;
+    $edit['options[expose][description]'] = $description;
+    $edit['options[value][min]'] = 26;
+    $edit['options[value][max]'] = 28;
+    $edit['options[operator]'] = 'between';
+    $this->drupalPostForm(NULL, $edit, t('Apply'));
+    $this->drupalPostForm('admin/structure/views/view/test_view', array(), t('Save'));
+    $this->assertConfigSchemaByName('views.view.test_view');
+    $this->drupalPostForm(NULL, array(), t('Update preview'));
+    // The first form item should have the label and description: the min field.
+    $this->assertEqual(trim($this->cssSelect('.form-item-age-min label')[0]), $label);
+    $this->assertEqual(trim($this->cssSelect('.form-item-age-min .description')[0]), $description);
+    // The other form item should have no label or description: the max field.
+    $this->assertEqual(count($this->cssSelect('.form-item-age-max label')), 0, $label_not_found);
+    $this->assertEqual(count($this->cssSelect('.form-item-age-max .description')), 0, $description_not_found);
+
+    // Next try two inputs and one select.
+    $this->drupalGet('admin/structure/views/nojs/handler/test_view/default/filter/age');
+    $edit = array();
+    $edit['options[expose][use_operator]'] = 1;
+    $this->drupalPostForm(NULL, $edit, t('Apply'));
+    $this->drupalPostForm('admin/structure/views/view/test_view', array(), t('Save'));
+    $this->assertConfigSchemaByName('views.view.test_view');
+    $this->drupalPostForm(NULL, array(), t('Update preview'));
+    // The first form item should have the label and description: the select.
+    $this->assertEqual(trim($this->cssSelect('.form-item-age-op label')[0]), $label);
+    $this->assertEqual(trim($this->cssSelect('.form-item-age-op .description')[0]), $description);
+    // The other form items should have no label or description: the min and max field.
+    $this->assertEqual(count($this->cssSelect('.form-item-age-min label')), 0, $label_not_found);
+    $this->assertEqual(count($this->cssSelect('.form-item-age-min .description')), 0, $description_not_found);
+    $this->assertEqual(count($this->cssSelect('.form-item-age-max label')), 0, $label_not_found);
+    $this->assertEqual(count($this->cssSelect('.form-item-age-max .description')), 0, $description_not_found);
+
+    // Last try one inputs and one select.
+    $this->drupalGet('admin/structure/views/nojs/handler/test_view/default/filter/age');
+    $edit = array();
+    $edit['options[operator]'] = '<';
+    $this->drupalPostForm(NULL, $edit, t('Apply'));
+    $this->drupalPostForm('admin/structure/views/view/test_view', array(), t('Save'));
+    $this->assertConfigSchemaByName('views.view.test_view');
+    $this->drupalPostForm(NULL, array(), t('Update preview'));
+    // The first form item should have the label and description: the select.
+    $this->assertEqual(trim($this->cssSelect('.form-item-age-op label')[0]), $label);
+    $this->assertEqual(trim($this->cssSelect('.form-item-age-op .description')[0]), $description);
+    // The other form item should have no label or description: the value field.
+    $this->assertEqual(count($this->cssSelect('.form-item-age-value label')), 0, $label_not_found);
+    $this->assertEqual(count($this->cssSelect('.form-item-age-value .description')), 0, $description_not_found);
   }
-
 }
