Angular 5: "No provider for ControlContainer"

Marvin H. picture Marvin H. · Feb 24, 2018 · Viewed 82.3k times · Source

I have a little web app with Angular 5 and out of a sudden I am getting this strange error message in my browser console:

ncaught Error: Template parse errors:
No provider for ControlContainer ("
</p>
<form class="container" (ngSubmit)="update()">
  [ERROR ->]<app-form-group-component 
[formGroup]="additionalInformation"></app-form-group-component>
      <button "): ng:///AppModule/KickoffComponent.html@4:2

That did not happen before and I am not aware of any made changes. And I have no idea what that message tries to tell me.

This is the component template of form-group which seems to be invalid somehow:

<div *ngFor='let e of formGroup' class="form-group">
<label for="{{e.key}}">{{e.label}}</label>
<input type="{{e.type}}" name="{{e.key}}" 
[(ngModel)]="e.value" class="form-control" 
[ngClass]='{"is-valid": e.valid === true && e.required === true}'
        />
    </div>

And this is the template where I consume form-group:

<form class="container" (ngSubmit)="update()">
 <app-form-group-component [formGroup]="additionalInformation"></app-form-group-component>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>
<app-notification [notification]="notification"></app-notification>

I stared at it for hours, but I can't find any mistake.

I should mention that I don't use Angular's FormGroup but my own solution (because I thought theirs to be overengineered and it didn't fit my specific needs). Could there be some kind of name collision? Of course, in the app.module I have imported the FormsModule for two-way binding to work and to intercept the form's submit. The notification-component at least works without complaints.

I would be very greatful for any help.

Edit: I was asked to share my TS code.

Failing component:

import { Component, Input } from '@angular/core';
import { FormGroup } from '../../models/form-group';

@Component({
  selector: 'app-form-group-component',
  templateUrl: './form-group.component.html',
})
export class FormGroupComponent {
  @Input() formGroup?: FormGroup
}

The type FormGroup is just an Array and the component is just meant to be a visual wrapper. There are no additional services involved or DI and without that component Angular compiles just fine. (formGroup is marked as optional because TS would keep complaining about it not being initialized, although at runtime it will always be initialized)

Component which hands over property:

import { Component, OnInit } from "@angular/core";
import { additionalInformation } from "./additional-information";
import { basicInformation } from "./basic-information";
...

@Component({
  selector: "app-kickoff",
  templateUrl: "./kickoff.component.html",
})
export class KickoffComponent implements OnInit {
  basicInformation: FormGroup = basicInformation;
  additionalInformation: FormGroup = additionalInformation;
  methods...
}

Edit: To answer @Andrei's question: I have no service or provider called ControlContainer. I just have three small services, none of them causes any trouble. As far as I can tell, ControlContainer has something to do with DI, but Angular's documentation on that topic is rather mystifying.

Answer

cyr_x picture cyr_x · Feb 24, 2018

The ControlContainer is a abstract class which is extended by the AbstractFormGroupDirective inside the ReactiveFormsModule.

The error is thrown if you're using the ReactiveFormsModule and a <form>-element without a FormGroup bound to it via [formGroup]="myForm".

To fix this error you have to create a FormGroup and bind it to your form:

<form class="container" [formGroup]="myForm" (ngSubmit)="update()">

Also make sure you have both the FormsModule and the ReactiveFormsModule added to your module imports.