mat-form-field must contain a MatFormFieldControl
Asked Answered
B

43

506

We are trying to build our own form-field-Components at our Company. We are trying to wrap material design's Components like this:

field:

<mat-form-field>
    <ng-content></ng-content>
    <mat-hint align="start"><strong>{{hint}}</strong> </mat-hint>
    <mat-hint align="end">{{message.value.length}} / 256</mat-hint>
    <mat-error>This field is required</mat-error>
</mat-form-field>

textbox:

<field hint="hint">
    <input matInput 
    [placeholder]="placeholder" 
    [value]="value"
    (change)="onChange($event)" 
    (keydown)="onKeydown($event)" 
    (keyup)="onKeyup($event)" 
    (keypress)="onKeypress($event)">
</field>

Usage:

<textbox value="test" hint="my hint"></textbox>

This results in approximately this:

<textbox  placeholder="Personnummer/samordningsnummer" value="" ng-reflect-placeholder="Personnummer/samordningsnummer">
  <field>
    <mat-form-field class="mat-input-container mat-form-field">
      <div class="mat-input-wrapper mat-form-field-wrapper">
        <div class="mat-input-flex mat-form-field-flex">
          <div class="mat-input-infix mat-form-field-infix">
            <input _ngcontent-c4="" class="mat-input-element mat-form-field-autofill-control" matinput="" ng-reflect-placeholder="Personnummer/samordningsnummer" ng-reflect-value="" id="mat-input-2" placeholder="Personnummer/samordningsnummer" aria-invalid="false">
            <span class="mat-input-placeholder-wrapper mat-form-field-placeholder-wrapper"></span>
          </div>
        </div>
        <div class="mat-input-underline mat-form-field-underline">
          <span class="mat-input-ripple mat-form-field-ripple"></span>
        </div>
        <div class="mat-input-subscript-wrapper mat-form-field-subscript-wrapper"></div>
      </div>
    </mat-form-field>
  </field>
</textbox>

But I'm getting "mat-form-field must contain a MatFormFieldControl" in the console. I guess this has to do with mat-form-field not directly containing a matInput-field. But it is containing it, it's just withing the ng-content projection.

Here is a blitz: https://stackblitz.com/edit/angular-xpvwzf

Bracketing answered 12/10, 2017 at 8:42 Comment(7)
No, unfortunately not :/. I found this: github.com/angular/material2/issues/9411 and if I understand this correctly this is unsupported atm.Bracketing
Ok.. Thanks, I ended up making a component that just wraps up all the hints and validations and placed that under the input element.Duchamp
@ViktorEriksson If my answer was useful to you, do you care to accept it?Auckland
I'm sorry but it was not useful, my question has very little to do with that answer.Bracketing
material.angular.io/components/form-field/…Walk
My case, I used *ngIf in <input> tag. Moving the if condition out to a <ng-container> resolved my issue.Gamboge
Did you find a real solution to this since no answer come close to respond to your actual question?Engine
N
110

Import MatInputModule in your module.ts file and it will solve the problem.

import { MatInputModule } from '@angular/material/input';

The statement after it is the old answer.

Unfortunately content projection into mat-form-field is not supported yet. Please track the following github issue to get the latest news about it.

By now the only solution for you is either place your content directly into mat-form-field component or implement a MatFormFieldControl class thus creating a custom form field component.

Nadaba answered 4/4, 2018 at 18:51 Comment(6)
I came across this question googling an error message. The answer below, stating that MatInputModule needs to be imported solved my problem. Since this is the accepted answer, I'm adding the link here, hoping it will save other's time.Rude
My problem was that I had neglected to import 'FormsModule'. I hope this helps someone.Admissive
Also inside a <mat-form-field> tag you have to make sure you added correctly matInput attribute on every input tag or or matNativeControl attribute on every <select>Company
@CGFoX I wish they would update the documentation with this information and better examples...Celloidin
But you can kind of hack around it using ViewChild / ViewChildren: https://mcmap.net/q/75208/-content-projection-inside-angular-material-tableAmylolysis
If it's still not working, just run ng serve again 😉Capitoline
A
988

I was having a very similar issue; I imported MatFormFieldModule at my main module but forgot to add MatInputModule to the imports array, like so:

import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from "@angular/material/form-field";


@NgModule({
    imports: [
        MatFormFieldModule,
        MatInputModule
    ]
})
export class AppModule { }

More info here.

Auckland answered 17/10, 2017 at 17:6 Comment(7)
This is referenced in documentation now in Troubleshooting section of form-field : material.angular.io/components/form-field/… Look for Error: mat-form-field must contain a MatFormFieldControlInstantaneous
One day I will finally remember this...Stacee
correct path is - import { MatInputModule } from '@angular/material/input';Fashionable
@Fashionable This comment should be upvoted because his import was giving me errors. It's two separate paths!Goldberg
doesn't really work with Angular 15. Seems the problem with ng-content injection is not resolved yet.Emee
Thanks. The value of Stackoverflow being experiencedClifton
For future reference: We updated Angular to version with breaking changes. A choice was made to update only the imports and renaming. import { MatLegacyInputModule as MatInputModule } from '@angular/material/ If you are unlucky, stressed, or lack competence it might wake dragons. Read both the import and the imports.Squamous
A
462

Problem 1: MatInputModule Not imported

import MatInputModule and MatFormFieldModule inside module i.e. app.module.ts

import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from "@angular/material/form-field";

@NgModule({
    imports: [
        MatFormFieldModule,
        MatInputModule
    ]
})
export class AppModule { }

Problem 2: matInput - spellings mistake / forget to add

Be sure to add matInput and it is case-sensitive.

<mat-form-field>
    <input matInput type="text" />
</mat-form-field>

Problem 3: Invalid *ngIf or @if placement

Check that you don't have any condition on input tag that is going to be false in any case because mat-form-field looks for matInput inside it. Instead put *ngIf on mat-form-field tag.

<mat-form-field>
   <input matInput *ngIf="someCondition"> // don't add condition here, else add in mat-form-field tag
</mat-form-field>

credit to @William Herrmann for pointing out this problem#3

Problem 4: Still compiler giving ERROR

if angular compiler still giving error after fixing above given problems then you must try with restarting the app.

ng serve
Antlion answered 24/4, 2018 at 12:54 Comment(10)
I encountered this issue when "matInput" was missing from the input statement.Raimes
i've imported MatInputModule, MatFormFieldModule and Restart (ng serve). It works Fine now!Ruralize
exactly my problem was not inserted the 'matInput'. :'( tksHolmberg
Problem 4: having an *ngIf directive on the input[matInput] element. This was my mistake. I meant to put the *ngIf on the mat-form-field element itself.Mcculley
Problem 3. Empty content of <mat-form-field>. This means that you can use NgIf with <input>, but you need to guarantee that an input tag will be present under any condition.Francklyn
Thanks it worked but errors shown by Angular in console are confusing and not clear. they can easily say please import this or that module to resolve theproblem.Davin
I had a invariant of problem 2. when using a formControl from .ts my mistake was to use '<mat-input >' instead of '<input matInput>' <mat-form-field> <!-- this works, not using the '<mat-input>'' --> <input matInput [formControl]="nameFilter" name="name-filter" /> <!-- below does not work: gives error 'Error: mat-form-field must contain a MatFormFieldControl.' --> <!-- <mat-input [formControl]="nameFilter" name="name-filter"></mat-input> --> </mat-form-field>Heydon
I had the input element capitalized "<Input matInput ...>" thanks, this fixed itGurias
problem 5 : you must set the providers in you @component : providers: [{ provide: MatFormFieldControl, useExisting: MyComponent }]Quaver
Accepted answer pleaseZoarah
N
110

Import MatInputModule in your module.ts file and it will solve the problem.

import { MatInputModule } from '@angular/material/input';

The statement after it is the old answer.

Unfortunately content projection into mat-form-field is not supported yet. Please track the following github issue to get the latest news about it.

By now the only solution for you is either place your content directly into mat-form-field component or implement a MatFormFieldControl class thus creating a custom form field component.

Nadaba answered 4/4, 2018 at 18:51 Comment(6)
I came across this question googling an error message. The answer below, stating that MatInputModule needs to be imported solved my problem. Since this is the accepted answer, I'm adding the link here, hoping it will save other's time.Rude
My problem was that I had neglected to import 'FormsModule'. I hope this helps someone.Admissive
Also inside a <mat-form-field> tag you have to make sure you added correctly matInput attribute on every input tag or or matNativeControl attribute on every <select>Company
@CGFoX I wish they would update the documentation with this information and better examples...Celloidin
But you can kind of hack around it using ViewChild / ViewChildren: https://mcmap.net/q/75208/-content-projection-inside-angular-material-tableAmylolysis
If it's still not working, just run ng serve again 😉Capitoline
B
36

If anyone got stuck with this error after attempting to nest a <mat-checkbox>, be of good cheer! It doesn't work inside a <mat-form-field> tag.

Bowstring answered 22/5, 2019 at 13:4 Comment(4)
Indeed. For more detail, see https://mcmap.net/q/75209/-mat-form-field-must-contain-a-matformfieldcontrol-and-already-imported.Meunier
This was my caseFarmyard
Same for mat-slide-toggleMistakable
This Answer, has, in fact, made me of good cheer.Ligate
C
33

This can also happen if you have a proper input within a mat-form-field, but it has a ngIf on it. E.g.:

<mat-form-field>
    <mat-chip-list *ngIf="!_dataLoading">
        <!-- other content here -->
    </mat-chip-list>
</mat-form-field>

In my case, mat-chip-list is supposed to "appear" only after its data is loaded. However, the validation is performed and mat-form-field complains with

mat-form-field must contain a MatFormFieldControl

To fix it, the control must be there, so I have used [hidden]:

<mat-form-field>
    <mat-chip-list [hidden]="_dataLoading">
        <!-- other content here -->
    </mat-chip-list>
</mat-form-field>

An alternative solution is proposed by Mosta: move *ngIf for mat-form-field:

<mat-form-field *ngIf="!_dataLoading">
    <mat-chip-list >
        <!-- other content here -->
    </mat-chip-list>
</mat-form-field>
Canaster answered 22/11, 2018 at 15:26 Comment(3)
Thanks, instead of using hidden you can move the ngIf condition on the whole mat-form-field tagBushelman
same things occurs with an ngSwitchGiannagianni
This was my problem. The solution is a life saver.Primal
A
23

Quoting from the official documentation here:

Error: mat-form-field must contain a MatFormFieldControl

This error occurs when you have not added a form field control to your form field. If your form field contains a native <input> or <textarea> element, make sure you've added the matInput directive to it and have imported MatInputModule. Other components that can act as a form field control include <mat-select>, <mat-chip-list>, and any custom form field controls you've created.

Learn more about creating a "custom form field control" here

Aridatha answered 16/2, 2018 at 8:4 Comment(0)
C
19

I had this issue too, and I have <mat-select> element in my template, when I import the MatSelectModule into Module, it works, it doesn't make sense, but still I hope it can help you.

import { MatSelectModule } from '@angular/material/select';

imports: [
    BrowserModule,
    BrowserAnimationsModule,
    MatSidenavModule,
    MatButtonModule,
    MatIconModule,
    MatToolbarModule,
    MatFormFieldModule,
    MatProgressSpinnerModule,
    MatInputModule,
    MatCardModule,
    MatSelectModule
],

<div class="example-container">
    <mat-form-field>
        <input matInput placeholder="Input">
    </mat-form-field>
    
    <mat-form-field>
        <textarea matInput placeholder="Textarea"></textarea>
    </mat-form-field>
    
    <mat-form-field>
        <mat-select placeholder="Select">
            <mat-option value="option">Option</mat-option>
        </mat-select>
    </mat-form-field>
</div>
Courland answered 28/1, 2018 at 10:3 Comment(1)
It works as without importing the module the mat-form-field control does not understand what a mat-select is. When it is imported it can fix up all the information and therefore can parse the template without further error.Tortola
S
15
import {MatInputModule} from '@angular/material/input';



@NgModule({
    imports: [
        MatInputModule
    ],
    exports: [
        MatInputModule
    ]
})
Smokedry answered 15/1, 2020 at 8:14 Comment(2)
Welcome to stackoverflow. When answering questions, please add some explaination as to what your code snippet does and why it solves the OP's question. For more info check here How to AnswerArena
Why add it to your module's exports?Unmask
T
9

if anyone is trying to nest a <mat-radio-group> inside a <mat-form-field> like below, you will get this error

         <mat-form-field>
                <!-- <mat-label>Image Position</mat-label> -->
                <mat-radio-group aria-label="Image Position" [(ngModel)]="section.field_1">
                    <mat-radio-button value="left">Left</mat-radio-button>
                    <mat-radio-button value="right">Right</mat-radio-button>
                </mat-radio-group>
            </mat-form-field>

remove the parent <mat-form-field> tags

Teerell answered 13/11, 2019 at 5:48 Comment(2)
I was having this issue, and had a snippet of markup with this sort of thing. Removing the mat-form-field made the issue go away for me.Pinchbeck
Is there a reason that <mat-form-field> doesn't support radio group inside of it? I was having this issue too and didn't think to just remove the mat form field tags because it didn't seem like it would be the proper thing to do since so many materials UI form examples use <mat-form-field>. I have all the various material form input modules for forms, select dropdowns and radio groups defined in my app.module.ts like many of the other answers reference.Mikol
M
9

it means you are not importing MatInputModule like

import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from "@angular/material/form-field";

@NgModule({
    imports: [
        MatFormFieldModule,
        MatInputModule
    ]
})
export class AppModule { }
Malcom answered 3/8, 2021 at 17:56 Comment(1)
This answer is already given: https://mcmap.net/q/73929/-mat-form-field-must-contain-a-matformfieldcontrol. So the upvote is very suspiciousEmbrocation
B
7

I'm not sure if it could be this simple but I had the same issue, changing "mat-input" to "matInput" in the input field resolved the problem. In your case I see "matinput" and it's causing my app to throw the same error.

<input _ngcontent-c4="" class="mat-input-element mat-form-field-autofill-control" matinput="" ng-reflect-placeholder="Personnummer/samordningsnummer" ng-reflect-value="" id="mat-input-2" placeholder="Personnummer/samordningsnummer" aria-invalid="false">

"matinput"

enter image description here

"matInput"

enter image description here

Basting answered 15/10, 2017 at 19:51 Comment(4)
hmm not sure, you have pasted the generated output. In the real code it already is matInput, if you see "textbox-section". I have no problems getting it to work when just using material, its when trying to make my own compoenent with projection it stops working. My plunker seem to be having problems atm, hopefully it will fix itself during the day.Bracketing
Oh I see, my bad. This was a long shot anyway. I'll follow to see if anyone can actually come up with the correct lean angle, I'm curious about this issue.Basting
It happened with me, I have forgotten to change mdInput to matInput.Sweptback
Angular 5: the <input> tag attribute should be matInput instead of mat-input.Preferment
T
6

Angular 9+ ...Material 9+

I have noticed 3 mistakes can can give rise to the same error:

  1. Ensure you have imported MatFormFieldModule and MatInputModule in the app.module or the module.ts where your components are being imported(in case of nested modules)
  2. When you wrap material buttons or checkbox in mat-form-field. See the list of material components that can be wrapped with mat-form-field mat-form-field
  3. When you fail to include matInput in your tag. i.e <input matInput type="number" step="0.01" formControlName="price" />
Trajectory answered 27/6, 2020 at 8:1 Comment(1)
4. If you leave mat-form-field as an empty wrapperPronghorn
G
6

I had the problem occuring in one of my Karma tests

As most answers already pointed at, missing modules can cause problems and they must be reimported in the Karma TestBed as well. Also, it seems like we also need to import BrowserAnimationsModule to make everything work.

In my code below I have commented some modules that may not be useful for you, but the other 4 imports should definitely help !

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ EventFormComponent ],
      imports: [
        # HttpClientTestingModule,
        # RouterTestingModule,
        ReactiveFormsModule,
        MatFormFieldModule,
        MatInputModule,
        BrowserAnimationsModule,
        # TranslateModule.forRoot(),
      ],
    })
    .compileComponents();
  }));
Grateful answered 15/5, 2021 at 18:54 Comment(1)
You've taken me out from a hell pit :)Phantasmagoria
B
5

If all of the main code structure/configuration answers above don't solve your issue, here's one more thing to check: make sure that you haven't in some way invalidated your <input> tag.

For instance, I received the same mat-form-field must contain a MatFormFieldControl error message after accidentally putting a required attribute after a self-closing slash /, which effectively invalidated my <input/>. In other words, I did this (see the end of the input tag attributes):

wrong:

<input matInput type="text" name="linkUrl" [formControl]="listingForm.controls['linkUrl']" /required>

right:

<input matInput type="text" name="linkUrl" [formControl]="listingForm.controls['linkUrl']" required/>

If you make that mistake or something else to invalidate your <input>, then you could get the mat-form-field must contain a MatFormFieldControl error. Anyway, this is just one more thing to look for as you're debugging.

Brainard answered 15/6, 2019 at 21:9 Comment(2)
This also happens, apparently, if you don't have a proper closing tag. <input matInput placeholder="Placeholder"> did not work, but <input matInput placeholder="Placeholder" /> did.Wallsend
another unknown hero , thanks for saving my day! :)))))))Epicotyl
M
4

The same error can occur if you have a mat slide within a mat from field as the only element in my case I had

 <mat-form-field>
    <mat-slide-toggle [(ngModel)]="myvar">
       Some Text
     </mat-slide-toggle>
 </mat-form-field>

This might happen if you had several attributes within the <mat-form-field> Simple solution was to move the slide toggle to the root

Mikkanen answered 29/8, 2019 at 21:10 Comment(0)
G
3

I had accidentally removed the matInput directive from the input field which caused the same error.

eg.

<mat-form-field>
   <input [readOnly]="readOnly" name="amount" formControlName="amount" placeholder="Amount">
</mat-form-field>

fixed code

 <mat-form-field>
   <input matInput [readOnly]="readOnly" name="amount" formControlName="amount" placeholder="Amount">
</mat-form-field>
Governance answered 21/5, 2019 at 14:5 Comment(1)
Also necessary for textarea component, which was the case for me.Rhizoid
W
3

A partial solution is to wrap the material form field in a custom component and implement the ControlValueAccessor interface on it. Besides content projection the effect is pretty much the same.

See full example on Stackblitz.

I used FormControl (reactive forms) inside CustomInputComponent but FormGroup or FormArray should work too if you need a more complex form element.

app.component.html

<form [formGroup]="form" (ngSubmit)="onSubmit()">

  <mat-form-field appearance="outline" floatLabel="always" color="primary">
    <mat-label>First name</mat-label>
    <input matInput placeholder="First name" formControlName="firstName" required>
    <mat-hint>Fill in first name.</mat-hint>
    <mat-error *ngIf="firstNameControl.invalid && (firstNameControl.dirty || firstNameControl.touched)">
      <span *ngIf="firstNameControl.hasError('required')">
        You must fill in the first name.
      </span>
    </mat-error>
  </mat-form-field>

  <custom-input
    formControlName="lastName"
    [errorMessages]="errorMessagesForCustomInput"
    [hint]="'Fill in last name.'"
    [label]="'Last name'"
    [isRequired]="true"
    [placeholder]="'Last name'"
    [validators]="validatorsForCustomInput">
  </custom-input>

  <button mat-flat-button
    color="primary"
    type="submit"
    [disabled]="form.invalid || form.pending">
    Submit
  </button>

</form>

custom-input.component.html

<mat-form-field appearance="outline" floatLabel="always" color="primary">
  <mat-label>{{ label }}</mat-label>

  <input
    matInput
    [placeholder]="placeholder"
    [required]="isRequired"
    [formControl]="customControl"
    (blur)="onTouched()"
    (input)="onChange($event.target.value)">
  <mat-hint>{{ hint }}</mat-hint>

  <mat-error *ngIf="customControl.invalid && (customControl.dirty || customControl.touched)">
    <ng-container *ngFor="let error of errorMessages">
    <span *ngFor="let item of error | keyvalue">
      <span *ngIf="customControl.hasError(item.key)">
        {{ item.value }}
      </span>
    </span>
    </ng-container>
  </mat-error>
</mat-form-field>
Winther answered 14/11, 2019 at 12:21 Comment(0)
F
3

You have missed matInput directive in your input tag.

Footlocker answered 20/2, 2020 at 7:11 Comment(0)
B
3

use providers in component.ts file

@Component({
 selector: 'your-selector',
 templateUrl: 'template.html',
 styleUrls: ['style.css'],
 providers: [
 { provide: MatFormFieldControl, useExisting: FormFieldCustomControlExample }   
]
})
Bind answered 4/6, 2020 at 15:46 Comment(0)
M
3

New updated MatInput Module import is:

import {MatInputModule} from '@angular/material/input';

As per Angular Materials API

May answered 6/7, 2020 at 8:39 Comment(0)
A
3
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';

don't forget to add at first of <tabe></table>

 <mat-form-field>
        <mat-label>Filter</mat-label>
        <input matInput (keyup)="applyFilter($event)" placeholder="Ex. Helium" #input>
      </mat-form-field>

don't forget to add at last of <tabe></table>

<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4">
   No data matching the filter "{{input.value}}"
</td>
</tr>
Arraignment answered 11/2, 2021 at 11:54 Comment(0)
R
3

Uncaught Error: mat-form-field must contain a MatFormFieldControl.

This error occurs when 'MatInputModule' is missed in imports,

import { MatInputModule } from '@angular/material/input'
import { MatFormFieldModule } from '@angular/material/form-field'

@NgModule({
  imports: [
 MatInputModule ,
 MatFormFieldModule 
]})

importing MatInputModule in the module.ts file would help getting rid of the problem.

Reedbuck answered 30/7, 2021 at 6:2 Comment(0)
D
3

I forgot to add matInput property inside input tag

<mat-form-field appearance="outline">
    <mat-label>Mobile</mat-label>
    <input type="text"
           [(ngModel)]="parent.mobile"
           formControlName="mobile"
           id="mobile"
           name="mobile">
  </mat-form-field>

After adding it:

<mat-form-field appearance="outline">
    <mat-label>Mobile</mat-label>
    <input type="text"
       matInput
       [(ngModel)]="parent.mobile"
       formControlName="mobile"
       id="mobile"
       name="mobile">   
 </mat-form-field>
Descendible answered 11/12, 2022 at 14:56 Comment(0)
E
2

You could try following this guide and implement/provide your own MatFormFieldControl

Embrue answered 25/2, 2019 at 1:14 Comment(0)
H
2

In my case I changed this:

<mat-form-field>
  <input type="email" placeholder="email" [(ngModel)]="data.email">
</mat-form-field>

to this:

<mat-form-field>
  <input matInput type="email" placeholder="email" [(ngModel)]="data.email">
</mat-form-field>

Adding the matInput directive to the input tag was what fixed this error for me.

Hyder answered 23/4, 2019 at 5:4 Comment(0)
M
2

Unfortunately I can't just comment on some already good answers as I don't have the SO points yet, however, there are 3 key modules that you'll need to make sure you are importing into your component's parent module, aside from what you have to import into your component directly. I wanted to briefly share them and highlight what they do.

  1. MatInputModule
  2. MatFormFieldModule
  3. ReactiveFormsModule

The first two are for Angular Material. A lot of people new to Angular Material will instinctively come across one of these and not realize that building a form requires both.

So what's the difference between them?

MatFormFieldModule encompasses all the different types of form fields that Angular Material has available. This is more of a high level module for form fields in general, whereas the MatInputModule is specifically for 'input' field types, as opposed to select boxes, radio buttons, etc.

The third item on the above list is Angular's Reactive Forms Module. The Reactive Forms Module is responsible for a ton of under-the-hood Angular love. If you are going to work with Angular, I highly recommend that you spend some time reading Angular Docs. They have all of your answers. Building applications rarely DOESN'T involve forms, and more often than not, your application will involve reactive forms. For that reason, please take the time to read these two pages.

Angular Docs: Reactive Forms

Angular Docs: Reactive Forms Module

The first doc 'Reactive Forms' will be your most powerful weapon as you get started, and the second doc will be your most power weapon as you get on to more advanced applications of Angular Reactive Forms.

Remember, these need to be imported directly into your component's module, not the component you are using them in. If I remember correctly, in Angular 2, we imported the entire set of Angular Material modules in our main app module, and then imported what we needed in each of our components directly. The current method is much more efficient IMO because we are guaranteed to import the entire set of Angular Material modules if we only use a few of them.

I hope this provides a bit more insight into building forms with Angular Material.

Mullane answered 9/6, 2019 at 6:22 Comment(0)
S
2

MatRadioModule won't work inside MatFormField. The docs say

This error occurs when you have not added a form field control to your form field. If your form field contains a native or element, make sure you've added the matInput directive to it and have imported MatInputModule. Other components that can act as a form field control include < mat-select>, < mat-chip-list>, and any custom form field controls you've created.

Scabious answered 3/7, 2019 at 5:18 Comment(0)
S
2

In my case, one of my closing parenthesis for "onChanges()" were missed on the input element and thus the input element was apparently not being rendered at all:

<input mat-menu-item 
      matInput type="text" 
      [formControl]="myFormControl"
      (ngModelChange)="onChanged()>
Sainted answered 29/7, 2019 at 18:39 Comment(0)
D
2

You might have missed to import MatInputModule

Disoblige answered 10/9, 2019 at 8:12 Comment(0)
I
2

You need to import the MatInputModule into your app.module.ts file

import { MatInputModule} from '@angular/material';

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { CustomerPage } from './components/customer/customer';
import { CustomerDetailsPage } from "./components/customer-details/customer-details";
import { CustomerManagementPageRoutingModule } from './customer-management-routing.module';
import { MatAutocompleteModule } from '@angular/material/autocomplete'
import { ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule} from '@angular/material';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    CustomerManagementPageRoutingModule,
    MatAutocompleteModule,
    MatInputModule,
    ReactiveFormsModule,
    MatFormFieldModule
  ],
Isley answered 18/4, 2020 at 13:59 Comment(0)
S
2

For me the error was due to lack of <input> and formControl property in <mat-form-field></mat-form-field>

<form [formGroup]="FormName">
    <mat-form-field>
    <mat-label>Name</mat-label>
    </mat-form-field>
</form>

which is wrong.. Correct one is the below

<form [formGroup]="FormName">
    <mat-form-field>
    <mat-label>Name</mat-label>
    <input matInput formControlName="name">
    </mat-form-field>
</form>
Sundowner answered 10/5, 2021 at 14:51 Comment(0)
P
1

Note Some time Error occurs, when we use "mat-form-field" tag around submit button like:

<mat-form-field class="example-full-width">
   <button mat-raised-button type="submit" color="primary">  Login</button>
   </mat-form-field>

So kindly don't use this tag around submit button

Pedro answered 20/11, 2019 at 1:50 Comment(0)
F
1

You can set appearance="fill" inside your mat-form-field tag, it works for me

<form class="example-form">
  <mat-form-field class="example-full-width" appearance="fill">
    <mat-label>Username Or Email</mat-label>
    <input matInput placeholder="Username Or Email" type="text">
  </mat-form-field>

  <mat-form-field class="example-full-width" appearance="fill">
    <mat-label>Password</mat-label>
    <input matInput placeholder="Password" type="password">
  </mat-form-field>
</form>
Francis answered 4/6, 2020 at 11:36 Comment(1)
This fixed my issue. Can you please explain what appearence = "fill" is doing hereMarthamarthe
H
1

if there is input tag under mat-form-field then each input must have matInput

Herb answered 2/12, 2021 at 17:52 Comment(0)
P
0

i was getting the same issue due to commented element as follows.

<mat-form-field>
    <mat-label>Database</mat-label>
    <!-- <mat-select>
        <mat-option *ngFor="let q of queries" [value]="q.id">
            {{q.name}}
        </mat-option>
    </mat-select>  -->
</mat-form-field>

form field should have element! (e.g. the input, textarea, select, etc.)

Photoelasticity answered 11/2, 2020 at 8:57 Comment(0)
D
0

I had the module imported and directive set and after executing 'ng add @angular/material' again it started working. Maybe it would be enough just to restart app with 'ng serve'

Dippold answered 20/9, 2020 at 6:31 Comment(0)
P
0

I had the same error message, but in my case, nothing above didn't fix the problem. The solution was in "label". You need to add 'mat-label' and to put your input inside 'label' tags also. Solution of my problem is in the snippet below:

  <mat-label>
     Username
  </mat-label>
  <label>
    <input 
       matInput 
       type="text" 
       placeholder="Your username" 
       formControlName="username"/>
  </label>
Polyploid answered 29/9, 2020 at 15:50 Comment(0)
M
0

This error appears also when simply by mistake input is placed out of the mat-form-field. To fix it just bring it inside like below:

Bad code:

<mat-form-field class="full-width">
</mat-form-field>
<input matInput placeholder="Title" formControlName="title" #title />

Fix:

<mat-form-field class="full-width">
    <input matInput placeholder="Title" formControlName="title" #title />
</mat-form-field>
Marbut answered 26/10, 2020 at 10:8 Comment(0)
H
0

100% solution guaranteed Just add matInput directive to each input, matselect and mat-chip-list enter image description here

Herb answered 9/7, 2021 at 10:51 Comment(0)
Y
0

In my case it was the TranslocoService service which probably messes with the after init.

My code was like this :

<mat-form-field
    class="fuse-mat-dense fuse-mat-no-subscript fuse-mat-rounded w-full min-w-50">
    <mat-icon
        class="icon-size-5"
        matPrefix
        [svgIcon]="'heroicons_solid:search'"></mat-icon>
    <input
        *transloco="let t"
        (keyup.enter)="searchByCustomerName()"
        matInput
        [formControl]="searchInputControl"
        [autocomplete]="'off'"
        placeholder="{{t('customer.management.customers.search.customer.name')}}">
</mat-form-field>

I have changed it like this.

<mat-form-field
    class="fuse-mat-dense fuse-mat-no-subscript fuse-mat-rounded w-full min-w-50">
    <mat-icon
        class="icon-size-5"
        matPrefix
        [svgIcon]="'heroicons_solid:search'"></mat-icon>
    <input
        (keyup.enter)="searchByCustomerName()"
        matInput
        [formControl]="searchInputControl"
        [autocomplete]="'off'"
        [placeholder]="searchBarPlaceHolder">
</mat-form-field>

The place holder value comes from a field at the Component. After this modification the error has gone. If you are using transloco you can try this.

Yes answered 28/9, 2021 at 18:22 Comment(0)
R
0

The idea of implementation doesn't make much sense, why do you need to add input as ng-content?

You just need to create an element that holds mat-form-field, input and it's parameters; and all the other things from mat-form-field, such as label and hint.

NOTE: the implementation below is quite old and should be upgraded, if you have any questions or ideas, please let me know in the comments

So create one and pass required parameters:

import { Component, forwardRef, Input, Provider } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { StringOrNull } from '../../../app.types';

export const FORM_FIELD_INPUT_TYPES = {
  checkbox: 'checkbox',
  color: 'color',
  date: 'date',
  dateTime: 'datetime',
  email: 'email',
  file: 'file',
  image: 'image',
  month: 'month',
  number: 'number',
  password: 'password',
  radio: 'radio',
  range: 'range',
  reset: 'reset',
  search: 'search',
  select: 'select',
  telephone: 'telephone',
  text: 'text',
  time: 'time',
  url: 'url',
  week: 'week',
} as const;
export const FORM_FIELD__VALUE_ACCESSOR_PROVIDER: Provider = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => FormFieldComponent),
  multi: true
};
export const FORM_FIELD_ERRORS = {
  required: {
    key: 'required',
    message: 'This field is required'
  }
};

export const FORM_FIELD_SELECT_OPTION_DIVIDER_TITLE = 'divider' as const;

export interface FormField extends Partial<FormFieldSelect> {
  hint: StringOrNull;
  label: StringOrNull;
  inputType: FormFieldInputType;
  formControl: FormControl,
}
export type FormFieldInputType = (typeof FORM_FIELD_INPUT_TYPES)[keyof typeof FORM_FIELD_INPUT_TYPES];
export type FormFieldSelect = { selectOptions: Array<FormFieldSelectOption> };
export type FormFieldSelectOption = {
  title: string|typeof FORM_FIELD_SELECT_OPTION_DIVIDER_TITLE;
  value: any;
};


@Component({
  selector: 'app-form-field',
  template: `
      <mat-form-field>
          <ng-template #inputTemplate>
              <input
                matInput
                [formControl]="formControl"
                [required]="required"
                [type]="inputType">
          </ng-template>
          <ng-template #inputSelectTemplate>
              <mat-select>
                  <mat-option
                    [value]="null">
                      Null
                  </mat-option>
                  <ng-container
                    *ngFor="let option of selectOptions"
                    [ngSwitch]="option.title">
                      <mat-divider *ngSwitchCase="'${FORM_FIELD_SELECT_OPTION_DIVIDER_TITLE}'">
                      </mat-divider>
                      <mat-option
                        *ngSwitchDefault
                        [value]="option.value">
                          {{option.title}}
                      </mat-option>
                  </ng-container>
              </mat-select>
          </ng-template>
          <ng-container [ngSwitch]="inputType">
              <ng-container
                *ngSwitchDefault
                [ngTemplateOutlet]="inputTemplate">
              </ng-container>
              <ng-container
                *ngSwitchCase="'${FORM_FIELD_INPUT_TYPES.select}'"
                [ngTemplateOutlet]="inputSelectTemplate">
              </ng-container>
          </ng-container>
          <mat-label *ngIf="label">
              {{label}}
          </mat-label>
          <mat-hint *ngIf="hint">
              {{hint}}
          </mat-hint>
          <mat-error *ngIf="formControl.hasError('${FORM_FIELD_ERRORS.required.key}')">
              ${FORM_FIELD_ERRORS.required.message}
          </mat-error>
      </mat-form-field>
  `,
  styles: [],
  providers: [
    FORM_FIELD__VALUE_ACCESSOR_PROVIDER,
  ]
})
export class FormFieldComponent implements ControlValueAccessor, FormField {

  @Input() set disabled(disabled: boolean) {
    if (disabled) {
      this.formControl?.disable();
    } else {
      this.formControl?.enable();
    }
  }
  @Input() formControl: FormControl = new FormControl();
  @Input() hint: StringOrNull = null;
  @Input() label: StringOrNull = null;
  @Input() required: boolean = false;
  @Input() inputType: FormFieldInputType = FORM_FIELD_INPUT_TYPES.text;
  @Input() selectOptions: Array<FormFieldSelectOption> = [];

  onChange = () => {};
  onTouch = () => {};

  registerOnChange(func: any): void {
    this.onChange = func;
  }

  registerOnTouched(func: any): void {
    this.onTouch = func;
  }

  setDisabledState(disabled: boolean): void { }

  writeValue(obj: any): void { }
}

After that I can create custom components for my project, naming those:

  • form-field-boolean
  • form-field-text
  • form-field-lookup

and so on. This is the correct implementation that you can use all over and be sure that everything is easy to fix. No need to use ng-content to pass input that has a just a few parameters that could be passed directly into the component.

Repeal answered 28/7, 2023 at 0:40 Comment(0)
A
-1

I had same issue

issue is simple

only you must import two modules to your project

MatFormFieldModule MatInputModule

Atc answered 2/1, 2020 at 17:22 Comment(0)
D
-4

Every one have explained how he got this problem solved but none of the answers solved my problem and I started getting annoyed when I found out that before doing all that expalained in these answer,

you have to install ( add ) angular material to your project

ng add @angular/material

for me this was the reason for the problem.

Davin answered 12/12, 2021 at 10:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.