From 4f55daea968a97fb36ca0a1f896e592861d9bcf2 Mon Sep 17 00:00:00 2001 From: Zach Arend Date: Tue, 15 Nov 2022 19:10:20 +0000 Subject: [PATCH] fix(material/autocomplete): apply theme of parent form field to panel Apply the theme of the autocomplete's parent form field to its panel. Fix issue where theme color only applies to the input, and does not affect the panel. --- .../autocomplete/autocomplete-demo.html | 26 +++++++++++++------ src/dev-app/autocomplete/autocomplete-demo.ts | 10 +++++++ .../autocomplete/autocomplete-trigger.ts | 1 + .../autocomplete/autocomplete.spec.ts | 26 +++++++++++++++++-- src/material/autocomplete/autocomplete.ts | 17 ++++++++++++ .../public_api_guard/material/autocomplete.md | 2 ++ 6 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/dev-app/autocomplete/autocomplete-demo.html b/src/dev-app/autocomplete/autocomplete-demo.html index 35c345def16b..13ef205b7868 100644 --- a/src/dev-app/autocomplete/autocomplete-demo.html +++ b/src/dev-app/autocomplete/autocomplete-demo.html @@ -6,16 +6,16 @@
Reactive value: {{ stateCtrl.value | json }}
Reactive dirty: {{ stateCtrl.dirty }}
- + State - - - {{ state.name }} - ({{ state.code }}) - - + + + {{ state.name }} + ({{ state.code }}) + + @@ -23,6 +23,11 @@ + @@ -33,7 +38,7 @@
Template-driven dirty: {{ modelDir ? modelDir.dirty : false }}
- + State @@ -50,6 +55,11 @@ + diff --git a/src/dev-app/autocomplete/autocomplete-demo.ts b/src/dev-app/autocomplete/autocomplete-demo.ts index addac2539932..a64d9b87a03d 100644 --- a/src/dev-app/autocomplete/autocomplete-demo.ts +++ b/src/dev-app/autocomplete/autocomplete-demo.ts @@ -15,6 +15,7 @@ import {MatCardModule} from '@angular/material/card'; import {MatInputModule} from '@angular/material/input'; import {Observable} from 'rxjs'; import {map, startWith} from 'rxjs/operators'; +import {ThemePalette} from '@angular/material/core'; export interface State { code: string; @@ -52,6 +53,15 @@ export class AutocompleteDemo { tdDisabled = false; + reactiveStatesTheme: ThemePalette = 'primary'; + templateStatesTheme: ThemePalette = 'primary'; + + availableThemes = [ + {value: 'primary', name: 'Primary'}, + {value: 'accent', name: 'Accent'}, + {value: 'warn', name: 'Warn'}, + ]; + @ViewChild(NgModel) modelDir: NgModel; groupedStates: StateGroup[]; diff --git a/src/material/autocomplete/autocomplete-trigger.ts b/src/material/autocomplete/autocomplete-trigger.ts index e87871d23ab4..fb3e45afef4b 100644 --- a/src/material/autocomplete/autocomplete-trigger.ts +++ b/src/material/autocomplete/autocomplete-trigger.ts @@ -666,6 +666,7 @@ export abstract class _MatAutocompleteTriggerBase this.autocomplete._setVisibility(); this.autocomplete._isOpen = this._overlayAttached = true; + this.autocomplete._setColor(this._formField?.color); // We need to do an extra `panelOpen` check in here, because the // autocomplete won't be shown if there are no options. diff --git a/src/material/autocomplete/autocomplete.spec.ts b/src/material/autocomplete/autocomplete.spec.ts index 2e855bef18f5..caba31899329 100644 --- a/src/material/autocomplete/autocomplete.spec.ts +++ b/src/material/autocomplete/autocomplete.spec.ts @@ -945,6 +945,28 @@ describe('MDC-based MatAutocomplete', () => { }); }); + describe('with theming', () => { + let fixture: ComponentFixture; + + beforeEach(() => { + fixture = createComponent(SimpleAutocomplete); + fixture.detectChanges(); + }); + + it('should transfer the theme to the autocomplete panel', () => { + fixture.componentInstance.theme = 'warn'; + fixture.detectChanges(); + + fixture.componentInstance.trigger.openPanel(); + fixture.detectChanges(); + + const panel = overlayContainerElement.querySelector( + '.mat-mdc-autocomplete-panel', + )! as HTMLElement; + expect(panel.classList).toContain('mat-warn'); + }); + }); + describe('keyboard events', () => { let fixture: ComponentFixture; let input: HTMLInputElement; @@ -3393,7 +3415,7 @@ describe('MDC-based MatAutocomplete', () => { }); const SIMPLE_AUTOCOMPLETE_TEMPLATE = ` - + State - @@ -3431,6 +3452,7 @@ class SimpleAutocomplete implements OnDestroy { ariaLabel: string; ariaLabelledby: string; panelClass = 'class-one class-two'; + theme: string; openedSpy = jasmine.createSpy('autocomplete opened spy'); closedSpy = jasmine.createSpy('autocomplete closed spy'); diff --git a/src/material/autocomplete/autocomplete.ts b/src/material/autocomplete/autocomplete.ts index 1098da961b9e..01fe3576ab02 100644 --- a/src/material/autocomplete/autocomplete.ts +++ b/src/material/autocomplete/autocomplete.ts @@ -34,6 +34,7 @@ import { CanDisableRipple, _MatOptionBase, _MatOptgroupBase, + ThemePalette, } from '@angular/material/core'; import {ActiveDescendantKeyManager} from '@angular/cdk/a11y'; import {BooleanInput, coerceBooleanProperty, coerceStringArray} from '@angular/cdk/coercion'; @@ -122,6 +123,14 @@ export abstract class _MatAutocompleteBase } _isOpen: boolean = false; + /** @docs-private Sets the theme color of the panel. */ + _setColor(value: ThemePalette) { + this._color = value; + this._setThemeClasses(this._classList); + } + /** @docs-private theme color of the panel */ + private _color: ThemePalette; + // The @ViewChild query for TemplateRef here needs to be static because some code paths // lead to the overlay being created before change detection has finished for this component. // Notably, another component may trigger `focus` on the autocomplete-trigger. @@ -206,6 +215,7 @@ export abstract class _MatAutocompleteBase } this._setVisibilityClasses(this._classList); + this._setThemeClasses(this._classList); this._elementRef.nativeElement.className = ''; } _classList: {[key: string]: boolean} = {}; @@ -296,6 +306,13 @@ export abstract class _MatAutocompleteBase classList[this._visibleClass] = this.showPanel; classList[this._hiddenClass] = !this.showPanel; } + + /** Sets the theming classes on a classlist based on the theme of the panel. */ + private _setThemeClasses(classList: {[key: string]: boolean}) { + classList['mat-primary'] = this._color === 'primary'; + classList['mat-warn'] = this._color === 'warn'; + classList['mat-accent'] = this._color === 'accent'; + } } @Component({ diff --git a/tools/public_api_guard/material/autocomplete.md b/tools/public_api_guard/material/autocomplete.md index 9f295af2b441..2c6f092ee75e 100644 --- a/tools/public_api_guard/material/autocomplete.md +++ b/tools/public_api_guard/material/autocomplete.md @@ -38,6 +38,7 @@ import { QueryList } from '@angular/core'; import { ScrollStrategy } from '@angular/cdk/overlay'; import { SimpleChanges } from '@angular/core'; import { TemplateRef } from '@angular/core'; +import { ThemePalette } from '@angular/material/core'; import { ViewContainerRef } from '@angular/core'; import { ViewportRuler } from '@angular/cdk/scrolling'; @@ -123,6 +124,7 @@ export abstract class _MatAutocompleteBase extends _MatAutocompleteMixinBase imp readonly optionSelected: EventEmitter; panel: ElementRef; panelWidth: string | number; + _setColor(value: ThemePalette): void; _setScrollTop(scrollTop: number): void; _setVisibility(): void; showPanel: boolean;