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'}} + +
+ + Number + + + @for (option of filteredOptions; track option) { + {{option}} + } + + +
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

+

+ + Revert value to + + None + @for (state of states; track state) { + + {{ state.name }} + ({{ state.code }}) + + } + + +

@@ -76,7 +91,8 @@ + [requireSelection]="templateRequireSelection" + [revertToValue]="templateRevertToValue"> @for (state of tdStates; track state) { @@ -113,6 +129,19 @@ Require Selection

+

+ + Revert value to + + None + @for (state of states; track state) { + + {{ state.name }} + + } + + +