diff --git a/src/material/timepicker/timepicker-input.ts b/src/material/timepicker/timepicker-input.ts index 8bb06ea23a07..3912a236e2d8 100644 --- a/src/material/timepicker/timepicker-input.ts +++ b/src/material/timepicker/timepicker-input.ts @@ -41,7 +41,7 @@ import {MAT_INPUT_VALUE_ACCESSOR} from '../input'; import {Subscription} from 'rxjs'; import {DOWN_ARROW, ESCAPE, hasModifierKey, UP_ARROW} from '@angular/cdk/keycodes'; import {validateAdapter} from './util'; -import {DOCUMENT} from '@angular/common'; +import {_getFocusedElementPierceShadowDom} from '@angular/cdk/platform'; /** * Input that can be used to enter time and connect to a `mat-timepicker`. @@ -82,7 +82,6 @@ import {DOCUMENT} from '@angular/common'; }) export class MatTimepickerInput implements ControlValueAccessor, Validator, OnDestroy { private _elementRef = inject>(ElementRef); - private _document = inject(DOCUMENT); private _dateAdapter = inject>(DateAdapter, {optional: true})!; private _dateFormats = inject(MAT_DATE_FORMATS, {optional: true})!; private _formField = inject(MAT_FORM_FIELD, {optional: true}); @@ -406,7 +405,7 @@ export class MatTimepickerInput implements ControlValueAccessor, Validator, O /** Whether the input is currently focused. */ private _hasFocus(): boolean { - return this._document.activeElement === this._elementRef.nativeElement; + return _getFocusedElementPierceShadowDom() === this._elementRef.nativeElement; } /** Gets a function that can be used to validate the input. */ diff --git a/src/material/timepicker/timepicker.spec.ts b/src/material/timepicker/timepicker.spec.ts index d147c6f6c58c..078fffa50be7 100644 --- a/src/material/timepicker/timepicker.spec.ts +++ b/src/material/timepicker/timepicker.spec.ts @@ -1,4 +1,4 @@ -import {Component, inject, Provider, signal, ViewChild} from '@angular/core'; +import {Component, inject, Provider, signal, ViewChild, ViewEncapsulation} from '@angular/core'; import {ComponentFixture, fakeAsync, flush, TestBed} from '@angular/core/testing'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {DateAdapter, provideNativeDateAdapter} from '../core'; @@ -299,6 +299,15 @@ describe('MatTimepicker', () => { fixture.detectChanges(); }).toThrowError(/MatTimepicker can only be registered with one input at a time/); }); + + it('input should be properly formatted when in shadow DOM', () => { + const fixture = TestBed.createComponent(TimepickerInShadowDom); + fixture.detectChanges(); // So that TimepickerInput.timepicker gets set. + const input = fixture.nativeElement.shadowRoot.querySelector('.mat-timepicker-input'); + typeInElement(input, '13:37'); + fixture.detectChanges(); + expect(input.value).toBe('13:37'); + }); }); describe('opening and closing', () => { @@ -1413,3 +1422,13 @@ class TimepickerWithMultipleInputs {} class TimepickerWithoutInput { @ViewChild(MatTimepicker) timepicker: MatTimepicker; } + +@Component({ + template: ` + + + `, + imports: [MatTimepicker, MatTimepickerInput], + encapsulation: ViewEncapsulation.ShadowDom, +}) +class TimepickerInShadowDom {}