diff --git a/scripts/check-mdc-tests-config.ts b/scripts/check-mdc-tests-config.ts index 17017e95e54f..3197bc8d0b0b 100644 --- a/scripts/check-mdc-tests-config.ts +++ b/scripts/check-mdc-tests-config.ts @@ -75,6 +75,7 @@ export const config = { 'should update the outline gap if the direction changes', 'should update the outline gap correctly if the direction changes multiple times', 'should calculate the outline gaps inside the shadow DOM', + 'should recalculate the outline gap when the label changes to empty after init', 'should be legacy appearance if no default options provided', 'should be legacy appearance if empty default options provided', ], diff --git a/src/material/form-field/form-field.ts b/src/material/form-field/form-field.ts index 0cba8d23a34d..ede0e03ebc4c 100644 --- a/src/material/form-field/form-field.ts +++ b/src/material/form-field/form-field.ts @@ -549,20 +549,26 @@ export class MatFormField */ updateOutlineGap() { const labelEl = this._label ? this._label.nativeElement : null; + const container = this._connectionContainerRef.nativeElement; + const outlineStartSelector = '.mat-form-field-outline-start'; + const outlineGapSelector = '.mat-form-field-outline-gap'; - if ( - this.appearance !== 'outline' || - !labelEl || - !labelEl.children.length || - !labelEl.textContent!.trim() - ) { + // getBoundingClientRect isn't available on the server. + if (this.appearance !== 'outline' || !this._platform.isBrowser) { return; } - if (!this._platform.isBrowser) { - // getBoundingClientRect isn't available on the server. + // If there is no content, set the gap elements to zero. + if (!labelEl || !labelEl.children.length || !labelEl.textContent!.trim()) { + const gapElements = container.querySelectorAll( + `${outlineStartSelector}, ${outlineGapSelector}`, + ); + for (let i = 0; i < gapElements.length; i++) { + gapElements[i].style.width = '0'; + } return; } + // 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 (!this._isAttachedToDOM()) { @@ -573,9 +579,8 @@ export class MatFormField let startWidth = 0; let gapWidth = 0; - const container = this._connectionContainerRef.nativeElement; - const startEls = container.querySelectorAll('.mat-form-field-outline-start'); - const gapEls = container.querySelectorAll('.mat-form-field-outline-gap'); + const startEls = container.querySelectorAll(outlineStartSelector); + const gapEls = container.querySelectorAll(outlineGapSelector); if (this._label && this._label.nativeElement.children.length) { const containerRect = container.getBoundingClientRect(); diff --git a/src/material/input/input.spec.ts b/src/material/input/input.spec.ts index c81888a72f33..f3fd311ba2ad 100644 --- a/src/material/input/input.spec.ts +++ b/src/material/input/input.spec.ts @@ -1761,6 +1761,34 @@ describe('MatInput with appearance', () => { expect(parseInt(outlineStart.style.width || '0')).toBeGreaterThan(0); expect(parseInt(outlineGap.style.width || '0')).toBeGreaterThan(0); })); + + it('should recalculate the outline gap when the label changes to empty after init', fakeAsync(() => { + fixture.destroy(); + TestBed.resetTestingModule(); + + const outlineFixture = createComponent(MatInputWithAppearanceAndLabel); + + outlineFixture.componentInstance.appearance = 'outline'; + outlineFixture.detectChanges(); + flush(); + outlineFixture.detectChanges(); + + const wrapperElement = outlineFixture.nativeElement; + const outlineStart = wrapperElement.querySelector('.mat-form-field-outline-start'); + const outlineGap = wrapperElement.querySelector('.mat-form-field-outline-gap'); + + expect(parseInt(outlineStart.style.width)).toBeGreaterThan(0); + expect(parseInt(outlineGap.style.width)).toBeGreaterThan(0); + + outlineFixture.componentInstance.labelContent = ''; + outlineFixture.detectChanges(); + + outlineFixture.componentInstance.formField.updateOutlineGap(); + outlineFixture.detectChanges(); + + expect(parseInt(outlineStart.style.width)).toBe(0); + expect(parseInt(outlineGap.style.width)).toBe(0); + })); }); describe('MatFormField default options', () => {