I'm receiving the following error from Angular Material when I try to use a <mat-label>
element inside a simple <mat-form-field>
:
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 ponent:
The ponent 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:
I'm receiving the following error from Angular Material when I try to use a <mat-label>
element inside a simple <mat-form-field>
:
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 ponent:
The ponent 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/ponents/select/overview
Share Improve this question edited Dec 31, 2023 at 11:11 Thomas Zimmermann asked Oct 18, 2023 at 12:58 Thomas ZimmermannThomas Zimmermann 1,96711 silver badges22 bronze badges 15- 1 Where is the error ing from? Your browser? Your IDE? Some kind of lint/test? – Chris Barr Commented Oct 18, 2023 at 13:05
- It is in the browser's console, in chrome – Thomas Zimmermann Commented Oct 18, 2023 at 13:07
- 1 Can you share your definition of "years"? – Tom Commented Oct 18, 2023 at 13:08
-
The years variable is an array of string:
string[]
– Thomas Zimmermann Commented Oct 18, 2023 at 13:09 -
1
I mean looking at the Material docs for a select menu you seem to be doing it correctly. What does the rendered HTML show, what
id
is thefor
referencing on the label? Also, possibly check out this answer – Chris Barr Commented Oct 18, 2023 at 13:12
7 Answers
Reset to default 1The problem is that a mat-select is not an labelable element and the "for" of the label indicate the "mat-select "id"
We can remove it using a directive. If you use the selector mat-select only need import the directive in the module or in the ponent if you're using standalone ponents
@Directive({
selector: 'mat-select',
})
export class RemoveFor implements AfterViewInit {
constructor(private el:ElementRef){}
ngAfterViewInit()
{
setTimeout(()=>{
const label=this.el.nativeElement.parentNode.getElementsByTagName('label')
if (label.length && label[0].getAttribute('for'))
label[0].removeAttribute('for')
})
}
}
import { Directive, AfterViewInit, ElementRef } from '@angular/core';
@Directive({
selector: 'mat-select[removeFor]'
})
export class RemoveForDirective implements AfterViewInit {
constructor(private el: ElementRef) {}
ngAfterViewInit() {
setTimeout(() => {
const label = this.el.nativeElement.parentNode.querySelector('label');
if (label && label.getAttribute('for')) {
label.removeAttribute('for');
}
});
}
}
The selector is specified as mat-select[removeFor]
to apply the directive only to mat-select elements with the removeFor attribute.
The querySelector method is used to select the label associated with the mat-select element. If a label with a for attribute is found, the for attribute is removed using removeAttribute.
Make sure to add this directive to the declarations array of your module to use it in your application.
Additionally, ensure that the directive is applied to the mat-select elements where you want to remove the for attribute from the associated label.
Now, you can use the removeFor attribute on mat-select elements in your HTML templates to apply the directive:
<mat-form-field>
<mat-label>Favorite food</mat-label>
<mat-select placeholder="Select an option" removeFor>
<mat-option value="pizza">Pizza</mat-option>
<mat-option value="pasta">Pasta</mat-option>
<mat-option value="burger">Burger</mat-option>
</mat-select>
</mat-form-field>
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 ponents 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.
I ran into this same issue, and found your thread. I ended up using a mat-placeholder instead of a mat-label. I'm using angular material version 16.
<mat-form-field class="selectControl">
<mat-placeholder><mat-icon aria-hidden="false" aria-label="info" matTooltip="Foo" color="primary">info</mat-icon> Label Here:</mat-placeholder>
<mat-select [formControl]="matSelect" class="position-Select" (selectionChange)="doSomething($event)">
<mat-option *ngFor="let foo of foos" [value]="object.id">
{{ object.name }}
</mat-option>
</mat-select>
</mat-form-field>
I'm having an issue with the mat-form-field being 16px padding on the top and bottom that makes the mat-select not be the same size vertically as the other mat-form-fields, but this got past the label for issue.
<input matInput style="width: 0px;">
Very annoying issue. I added this line in the mat-form-field and the error disappeared.
So far this does seem to be the only hack that works. Is there a better way to do this?
<mat-form-field class="selectControl">
<mat-label>Label</mat-label>
<input matInput style="width: 0px;">
<mat-select [formControl]="matSelect" class="position-Select" (selectionChange)="doSomething($event)">
<mat-option *ngFor="let foo of foos" [value]="object.id">
{{ object.name }}
</mat-option>
</mat-select>
</mat-form-field>
By adding a hidden element, this error can be avoided. Temporary solutions, informal.
<mat-form-field color="accent">
<mat-label>Year</mat-label>
<select id="year-select" style="display: none;"></select> <!-- add this line -->
<mat-select id="year-select" [value]="stateService.currentYear.toString() (valueChange)="onYearChange($event)"> <!-- add the same `id` attribute as above -->
<mat-option *ngFor="let year of years" [value]="year">
{{year}}
</mat-option>
</mat-select>
</mat-form-field>
Found this solution here -> feat(material/form-field): add MatLabel input property to change use of html