From 8edb840441a4333e09a26d52a1befc6d0342a2ba Mon Sep 17 00:00:00 2001
From: Eric Kidder
Date: Wed, 7 May 2025 18:54:20 -0400
Subject: [PATCH] feat:(angular/component): Configurable reversion value for
requireSelection for MatAutocomplete
Adds a new input for `MatAutocomplete`: `revertValueTo`. This input works with `requireSelection`
and allows the developer to provide a value that should be reverted to _instead_ of `null`. One
use case for this feature is to have the autocomplete revert to the _last known_ value instead
of `null` with something like: `[revertValueTo]="formControl.value"`
This defaults to `null` in order to maintain backwards compatibility.
The use-case that led to this change is a time zone picker. If the user does not select a time
zone, it will revert to either the previously selected time zone or the browser's time zone.
Video using the demo app: https://www.youtube.com/watch?v=cqZ2WzNDZbk
---
.../autocomplete-revert-to-value-example.css | 10 ++
.../autocomplete-revert-to-value-example.html | 20 ++++
.../autocomplete-revert-to-value-example.ts | 36 ++++++++
.../material/autocomplete/index.ts | 1 +
src/dev-app/autocomplete/BUILD.bazel | 1 +
.../autocomplete/autocomplete-demo.html | 33 ++++++-
src/dev-app/autocomplete/autocomplete-demo.ts | 5 +
.../autocomplete/autocomplete-trigger.ts | 9 +-
src/material/autocomplete/autocomplete.md | 13 +++
.../autocomplete/autocomplete.spec.ts | 91 +++++++++++++++++++
src/material/autocomplete/autocomplete.ts | 12 +++
11 files changed, 227 insertions(+), 4 deletions(-)
create mode 100644 src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.css
create mode 100644 src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.html
create mode 100644 src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.ts
diff --git a/src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.css b/src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.css
new file mode 100644
index 000000000000..951aee759961
--- /dev/null
+++ b/src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.css
@@ -0,0 +1,10 @@
+.example-form {
+ min-width: 150px;
+ max-width: 500px;
+ width: 100%;
+ margin-top: 16px;
+}
+
+.example-full-width {
+ width: 100%;
+}
diff --git a/src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.html b/src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.html
new file mode 100644
index 000000000000..c40d79faf328
--- /dev/null
+++ b/src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.html
@@ -0,0 +1,20 @@
+Control value: {{myControl.value || 'empty'}}
+
+
diff --git a/src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.ts b/src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.ts
new file mode 100644
index 000000000000..4b3d3bb384df
--- /dev/null
+++ b/src/components-examples/material/autocomplete/autocomplete-revert-to-value/autocomplete-revert-to-value-example.ts
@@ -0,0 +1,36 @@
+import {Component, ElementRef, ViewChild} from '@angular/core';
+import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
+import {MatAutocompleteModule} from '@angular/material/autocomplete';
+import {MatInputModule} from '@angular/material/input';
+import {MatFormFieldModule} from '@angular/material/form-field';
+
+/**
+ * @title Revert to a given value instead of null for requireSelection
+ */
+@Component({
+ selector: 'autocomplete-revert-to-value-example',
+ templateUrl: 'autocomplete-revert-to-value-example.html',
+ styleUrl: 'autocomplete-revert-to-value-example.css',
+ imports: [
+ FormsModule,
+ MatFormFieldModule,
+ MatInputModule,
+ MatAutocompleteModule,
+ ReactiveFormsModule,
+ ],
+})
+export class AutocompleteRevertToValueExample {
+ @ViewChild('input') input: ElementRef;
+ myControl = new FormControl('');
+ options: string[] = ['One', 'Two', 'Three', 'Four', 'Five'];
+ filteredOptions: string[];
+
+ constructor() {
+ this.filteredOptions = this.options.slice();
+ }
+
+ filter(): void {
+ const filterValue = this.input.nativeElement.value.toLowerCase();
+ this.filteredOptions = this.options.filter(o => o.toLowerCase().includes(filterValue));
+ }
+}
diff --git a/src/components-examples/material/autocomplete/index.ts b/src/components-examples/material/autocomplete/index.ts
index 18aad314a477..a558e6aeedc0 100644
--- a/src/components-examples/material/autocomplete/index.ts
+++ b/src/components-examples/material/autocomplete/index.ts
@@ -6,4 +6,5 @@ export {AutocompleteOverviewExample} from './autocomplete-overview/autocomplete-
export {AutocompletePlainInputExample} from './autocomplete-plain-input/autocomplete-plain-input-example';
export {AutocompleteSimpleExample} from './autocomplete-simple/autocomplete-simple-example';
export {AutocompleteRequireSelectionExample} from './autocomplete-require-selection/autocomplete-require-selection-example';
+export {AutocompleteRevertToValueExample} from './autocomplete-revert-to-value/autocomplete-revert-to-value-example';
export {AutocompleteHarnessExample} from './autocomplete-harness/autocomplete-harness-example';
diff --git a/src/dev-app/autocomplete/BUILD.bazel b/src/dev-app/autocomplete/BUILD.bazel
index 8ed724206443..64ce915e9dae 100644
--- a/src/dev-app/autocomplete/BUILD.bazel
+++ b/src/dev-app/autocomplete/BUILD.bazel
@@ -20,6 +20,7 @@ ng_project(
"//src/material/dialog",
"//src/material/form-field",
"//src/material/input",
+ "//src/material/select",
],
)
diff --git a/src/dev-app/autocomplete/autocomplete-demo.html b/src/dev-app/autocomplete/autocomplete-demo.html
index 401f1180e4ae..d7b8ac8e15f1 100644
--- a/src/dev-app/autocomplete/autocomplete-demo.html
+++ b/src/dev-app/autocomplete/autocomplete-demo.html
@@ -20,7 +20,8 @@
[displayWith]="displayFn"
[hideSingleSelectionIndicator]="reactiveHideSingleSelectionIndicator"
[autoActiveFirstOption]="reactiveAutoActiveFirstOption"
- [requireSelection]="reactiveRequireSelection">
+ [requireSelection]="reactiveRequireSelection"
+ [revertToValue]="reactiveRevertToValue">
@for (state of reactiveStates; track state; let index = $index) {
{{ state.name }}
@@ -59,6 +60,20 @@
Require Selection