From bfc8944db453e8cb009b45406f32b74889c4feb3 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 11 Nov 2021 09:26:43 +0100 Subject: [PATCH] fix(material/form-field): outline gap not recalculated when switching to empty label We had a condition where `updateOutlineGap` wouldn't do anything if the label is empty. The problem is that the label could start off with content and then switch to being empty. These changes set the gap labels to zero width if the gap element is empty. Fixes #23943. --- scripts/check-mdc-tests-config.ts | 1 + src/material/form-field/form-field.ts | 27 +++++++++++++++----------- src/material/input/input.spec.ts | 28 +++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) 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', () => {