Search code examples
javascripthtmlangularangular-material

Incorrect use of <label for=FORM_ELEMENT> Angular Material


I'm receiving the following error from Angular Material when I try to use a <mat-label> element inside a simple <mat-form-field>:

Chrome console error

Here is the problematic code:

<mat-form-field color="accent">
  <mat-label>Year</mat-label>
  <mat-select [value]="stateService.currentYear.toString()"
              (valueChange)="onYearChange($event)">
    <mat-option *ngFor="let year of years"
                [value]="year">
      {{year}}
    </mat-option>
  </mat-select>
</mat-form-field>

Here is the rendered component:

enter image description here

The component is fully functional and the label is properly growing and shrinking when selecting and deselecting the widget. The problem is with this error popping in my developer console, which I want to discard (does not look very professional).

I tried to assign some ids, use different semantic, with no results so far.

Any idea on how to clear this error?

Edit (31/12/2023): My chrome's browser console also logs this error in the official select documentation: https://material.angular.io/components/select/overview


Solution

  • I found a hack to clear my browser console. Using a directive made it easy to fix the whole app at once. Applies to the mat-form-field elements.

    import {AfterViewInit, Directive, ElementRef} from "@angular/core";
    
    /**
     * Prevent our angular material floating label selects
     * inside mat-form-field from firing unwanted errors
     */
    @Directive({selector: "mat-form-field"})
    export class RemoveMatFormFieldLabelForDirective implements AfterViewInit {
    
      // Constructor
    
      constructor(private _elementRef: ElementRef) {
      }
    
      // After view init
    
      ngAfterViewInit(): void {
        const label = this._elementRef.nativeElement.querySelector("label");
        if (label && label.getAttribute("for")) {
    
          // If we just remove the for attribute, a warning message still remains
          label.removeAttribute("for");
    
          // Nesting a fictive input inside the label fixed the problem for me
          const fictiveInput = document.createElement("input");
          fictiveInput.style.display = "none";
          fictiveInput.setAttribute("name", "fictive-input");
          label.appendChild(fictiveInput);
    
        }
      }
    
    }
    

    This will fix a classic use of <mat-select> with floating label.

    HTML code:

    <mat-form-field appearance="outline">
      <mat-label>Year</mat-label>
      <mat-select [value]="currentYear"
                  (valueChange)="onYearChange($event)">
        <mat-option [value]=currentYear>
          {{ currentYear }}
        </mat-option>
        <mat-option *ngFor="let year of years"
                    [value]="year">
          {{ year }}
        </mat-option>
      </mat-select>
    </mat-form-field>
    

    Here is the Answer to this issue from the Angular material team:

    I believe this is a false positive with the checker and it's safe to ignore this. Closing send components doesn't have a hard requirement to cleanly pass automated a11y checks. Please let us know if you are having an a11y issue in your application.