diff --git a/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.css b/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.css
index 08fa67536b1f..951aee759961 100644
--- a/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.css
+++ b/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.css
@@ -2,6 +2,7 @@
   min-width: 150px;
   max-width: 500px;
   width: 100%;
+  margin-top: 16px;
 }
 
 .example-full-width {
diff --git a/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.html b/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.html
index 6b428b0b45c9..e5c96b37e9d3 100644
--- a/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.html
+++ b/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.html
@@ -1,18 +1,20 @@
+Control value: {{myControl.value || 'empty'}}
+
 
-
-Control value: {{myControl.value}}
diff --git a/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.ts b/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.ts
index a93619ae3748..5da4fc881088 100644
--- a/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.ts
+++ b/src/components-examples/material/autocomplete/autocomplete-require-selection/autocomplete-require-selection-example.ts
@@ -1,14 +1,12 @@
-import {Component, OnInit} from '@angular/core';
+import {Component, ElementRef, ViewChild} from '@angular/core';
 import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
-import {Observable} from 'rxjs';
-import {map, startWith} from 'rxjs/operators';
 import {NgFor, AsyncPipe} from '@angular/common';
 import {MatAutocompleteModule} from '@angular/material/autocomplete';
 import {MatInputModule} from '@angular/material/input';
 import {MatFormFieldModule} from '@angular/material/form-field';
 
 /**
- * @title Require an autocomplete option to be selected.
+ * @title Require an autocomplete option to be selected
  */
 @Component({
   selector: 'autocomplete-require-selection-example',
@@ -25,21 +23,18 @@ import {MatFormFieldModule} from '@angular/material/form-field';
     AsyncPipe,
   ],
 })
-export class AutocompleteRequireSelectionExample implements OnInit {
+export class AutocompleteRequireSelectionExample {
+  @ViewChild('input') input: ElementRef;
   myControl = new FormControl('');
-  options: string[] = ['One', 'Two', 'Three', 'Three', 'Four'];
-  filteredOptions: Observable;
+  options: string[] = ['One', 'Two', 'Three', 'Four', 'Five'];
+  filteredOptions: string[];
 
-  ngOnInit() {
-    this.filteredOptions = this.myControl.valueChanges.pipe(
-      startWith(''),
-      map(value => this._filter(value || '')),
-    );
+  constructor() {
+    this.filteredOptions = this.options.slice();
   }
 
-  private _filter(value: string): string[] {
-    const filterValue = value.toLowerCase();
-
-    return this.options.filter(option => option.toLowerCase().includes(filterValue));
+  filter(): void {
+    const filterValue = this.input.nativeElement.value.toLowerCase();
+    this.filteredOptions = this.options.filter(o => o.toLowerCase().includes(filterValue));
   }
 }
diff --git a/src/dev-app/autocomplete/autocomplete-demo.html b/src/dev-app/autocomplete/autocomplete-demo.html
index e2d04e637bd8..27960dc3fce6 100644
--- a/src/dev-app/autocomplete/autocomplete-demo.html
+++ b/src/dev-app/autocomplete/autocomplete-demo.html
@@ -1,21 +1,27 @@
 Space above cards: 
 
 
-  
-    Reactive length: {{ tempStates?.length }}
+  
+    Reactive length: {{ reactiveStates.length }}
     Reactive value: {{ stateCtrl.value | json }}
     Reactive dirty: {{ stateCtrl.dirty }}
 
     
       State
-      
+      
     
     
-      
         {{ state.name }}
          ({{ state.code }}) 
diff --git a/src/dev-app/autocomplete/autocomplete-demo.ts b/src/dev-app/autocomplete/autocomplete-demo.ts
index d43a358ad72d..8c87e89ae06c 100644
--- a/src/dev-app/autocomplete/autocomplete-demo.ts
+++ b/src/dev-app/autocomplete/autocomplete-demo.ts
@@ -14,8 +14,6 @@ import {MatButtonModule} from '@angular/material/button';
 import {MatCardModule} from '@angular/material/card';
 import {MatCheckboxModule} from '@angular/material/checkbox';
 import {MatInputModule} from '@angular/material/input';
-import {Observable} from 'rxjs';
-import {map, startWith} from 'rxjs/operators';
 import {ThemePalette} from '@angular/material/core';
 import {MatDialog, MatDialogModule, MatDialogRef} from '@angular/material/dialog';
 
@@ -50,12 +48,12 @@ type DisableStateOption = 'none' | 'first-middle-last' | 'all';
   ],
 })
 export class AutocompleteDemo {
-  stateCtrl = new FormControl({code: 'CA', name: 'California'});
+  stateCtrl = new FormControl();
   currentState = '';
   currentGroupedState = '';
   topHeightCtrl = new FormControl(0);
 
-  reactiveStates: Observable;
+  reactiveStates: State[];
   tdStates: State[];
 
   tdDisabled = false;
@@ -138,12 +136,8 @@ export class AutocompleteDemo {
   ].map((state, index) => ({...state, index}));
 
   constructor() {
-    this.tdStates = this.states;
-    this.reactiveStates = this.stateCtrl.valueChanges.pipe(
-      startWith(this.stateCtrl.value),
-      map(val => this.displayFn(val)),
-      map(name => this.filterStates(name)),
-    );
+    this.tdStates = this.states.slice();
+    this.reactiveStates = this.states.slice();
 
     this.filteredGroupedStates = this.groupedStates = this.states.reduce(
       (groups, state) => {
diff --git a/src/material/autocomplete/autocomplete-trigger.ts b/src/material/autocomplete/autocomplete-trigger.ts
index 9a2460b75c39..b2cd6c5612e4 100644
--- a/src/material/autocomplete/autocomplete-trigger.ts
+++ b/src/material/autocomplete/autocomplete-trigger.ts
@@ -470,7 +470,13 @@ export abstract class _MatAutocompleteTriggerBase
     if (this._previousValue !== value) {
       this._previousValue = value;
       this._pendingAutoselectedOption = null;
-      this._onChange(value);
+
+      // If selection is required we don't write to the CVA while the user is typing.
+      // At the end of the selection either the user will have picked something
+      // or we'll reset the value back to null.
+      if (!this.autocomplete || !this.autocomplete.requireSelection) {
+        this._onChange(value);
+      }
 
       if (!value) {
         this._clearPreviousSelectedOption(null, false);
diff --git a/src/material/autocomplete/autocomplete.spec.ts b/src/material/autocomplete/autocomplete.spec.ts
index ca4dd3f62773..27365fa5b76f 100644
--- a/src/material/autocomplete/autocomplete.spec.ts
+++ b/src/material/autocomplete/autocomplete.spec.ts
@@ -2622,7 +2622,7 @@ describe('MDC-based MatAutocomplete', () => {
       tick();
 
       expect(input.value).toBe('Cali');
-      expect(stateCtrl.value).toBe('Cali');
+      expect(stateCtrl.value).toEqual({code: 'CA', name: 'California'});
       expect(spy).not.toHaveBeenCalled();
 
       dispatchFakeEvent(document, 'click');