Skip to content

Commit

Permalink
fix(form-field): outline gap no calculated in shadow dom (#17303)
Browse files Browse the repository at this point in the history
Currently we check whether the form field is inside the DOM using `documentElement.contains(formField)` so that we don't try to calculate the outline gap. The problem is that `contains` won't catch elements inside the shadow DOM. These changes rework the check to use `getRootNode` instead.

Fixes #17262.
  • Loading branch information
crisbeto authored and jelbourn committed Oct 11, 2019
1 parent 9fe32c0 commit 1b94295
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
18 changes: 17 additions & 1 deletion src/material/form-field/form-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ export class MatFormField extends _MatFormFieldMixinBase
}
// If the element is not present in the DOM, the outline gap will need to be calculated
// the next time it is checked and in the DOM.
if (!document.documentElement!.contains(this._elementRef.nativeElement)) {
if (!this._isAttachedToDOM()) {
this._outlineGapCalculationNeededImmediately = true;
return;
}
Expand Down Expand Up @@ -582,4 +582,20 @@ export class MatFormField extends _MatFormFieldMixinBase
private _getStartEnd(rect: ClientRect): number {
return this._previousDirection === 'rtl' ? rect.right : rect.left;
}

/** Checks whether the form field is attached to the DOM. */
private _isAttachedToDOM(): boolean {
const element: HTMLElement = this._elementRef.nativeElement;

if (element.getRootNode) {
const rootNode = element.getRootNode();
// If the element is inside the DOM the root node will be either the document
// or the closest shadow root, otherwise it'll be the element itself.
return rootNode && rootNode !== element;
}

// Otherwise fall back to checking if it's in the document. This doesn't account for
// shadow DOM, however browser that support shadow DOM should support `getRootNode` as well.
return document.documentElement!.contains(element);
}
}
36 changes: 35 additions & 1 deletion src/material/input/input.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Platform, PlatformModule} from '@angular/cdk/platform';
import {Platform, PlatformModule, _supportsShadowDom} from '@angular/cdk/platform';
import {wrappedErrorMessage, MockNgZone} from '@angular/cdk/private/testing';
import {
createFakeEvent,
Expand All @@ -12,6 +12,8 @@ import {
Provider,
NgZone,
Directive,
ViewEncapsulation,
ElementRef,
} from '@angular/core';
import {ComponentFixture, fakeAsync, flush, TestBed} from '@angular/core/testing';
import {
Expand Down Expand Up @@ -1503,7 +1505,26 @@ describe('MatInput with appearance', () => {
}));


it('should calculate the outline gaps inside the shadow DOM', fakeAsync(() => {
if (!_supportsShadowDom()) {
return;
}

fixture.destroy();
TestBed.resetTestingModule();

const outlineFixture = createComponent(MatInputWithOutlineAppearanceInShadowDOM);
outlineFixture.detectChanges();
flush();
outlineFixture.detectChanges();

const formField = outlineFixture.componentInstance.formField.nativeElement;
const outlineStart = formField.querySelector('.mat-form-field-outline-start') as HTMLElement;
const outlineGap = formField.querySelector('.mat-form-field-outline-gap') as HTMLElement;

expect(parseInt(outlineStart.style.width || '0')).toBeGreaterThan(0);
expect(parseInt(outlineGap.style.width || '0')).toBeGreaterThan(0);
}));

});

Expand Down Expand Up @@ -2010,6 +2031,19 @@ class MatInputWithoutPlaceholder {
})
class MatInputWithOutlineInsideInvisibleElement {}

@Component({
template: `
<mat-form-field appearance="outline" #formField>
<mat-label>Hello</mat-label>
<input matInput>
</mat-form-field>
`,
encapsulation: ViewEncapsulation.ShadowDom
})
class MatInputWithOutlineAppearanceInShadowDOM {
@ViewChild('formField', {read: ElementRef, static: false}) formField: ElementRef<HTMLElement>;
}


// Styles to reset padding and border to make measurement comparisons easier.
const textareaStyleReset = `
Expand Down

0 comments on commit 1b94295

Please sign in to comment.