title: No provider for ControlContainer and No provider for ControlContainer
body: <p>I am working on an application using Angular2. 
    I am trying to use Reactive Forms in my application but I am running into some errors : </p>
  
  <p>The first error is about NgControl as below:</p>
  
  <blockquote>
    <p>No provider for NgControl ("</p>
    
    <p>div class="col-md-8"
                            [ERROR ->]input class="form-control" 
                                    id="productNameId" 
                      "): ProductEditComponent@16:24</p>
  </blockquote>
  
  <p>The second error is about ControlContainer as below:</p>
  
  <blockquote>
    <p>No provider for ControlContainer ("
                div
                        [ERROR ->]div formArrayName="tags"></p>
    
    <p>div class="row"></p>
    
    <p>button cl"):</p>
  </blockquote>
  
  <p>Htmm file is as below:</p>
  
  <pre><code> &lt;div class="panel panel-primary"&gt;
     &lt;div class="panel-heading"&gt;
        {{pageTitle}}
  &lt;/div&gt;
  
  &lt;div class="panel-body"&gt;
      &lt;form class="form-horizontal"
            novalidate
            (ngSubmit)="saveProduct()"
            formGroup="productForm" &gt;
          &lt;fieldset&gt;
              &lt;div class="form-group" 
                   [ngClass]="{'has-error': displayMessage.productName }"&gt;
                  &lt;label class="col-md-2 control-label" for="productNameId"&gt;Product Name&lt;/label&gt;
  
                  &lt;div class="col-md-8"&gt;
                      &lt;input class="form-control" 
                              id="productNameId" 
                              type="text" 
                              placeholder="Name (required)" 
                              formControlName="productName" /&gt;
                      &lt;span class="help-block" *ngIf="displayMessage.productName"&gt;
                              {{displayMessage.productName}}
                      &lt;/span&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
  
  
   &lt;div formArrayName="tags"&gt;
                  &lt;div class="row"&gt;
                      &lt;button class="col-md-offset-1 col-md-1 btn btn-default"
                              type="button"
                              (click)="addTag()"&gt;Add Tag
                      &lt;/button&gt;
                  &lt;/div&gt;
                  &lt;div class="form-group"
                      *ngFor="let tag of tags.controls; let i=index" &gt;
                      &lt;label class="col-md-2 control-label" [attr.for]="i"&gt;Tag&lt;/label&gt;
  
                      &lt;div class="col-md-8"&gt;
                          &lt;input class="form-control" 
                                  [id]="i" 
                                  type="text" 
                                  placeholder="Tag" 
                                  formControlName="i" /&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
      &lt;!--more piece of code here --&gt;
  </code></pre>
  
  <p>My component file is as below:</p>
  
  <pre><code>         import { Component, OnInit, AfterViewInit, OnDestroy, ViewChildren, ElementRef } from '@angular/core';
           import { FormBuilder, FormGroup, FormControl, FormArray, Validators, FormControlName,NgForm } from '@angular/forms';
           import { ActivatedRoute, Router  } from '@angular/router';
  
         import 'rxjs/add/operator/debounceTime';
         import 'rxjs/add/observable/fromEvent';
         import 'rxjs/add/observable/merge';
           import { Observable } from 'rxjs/Observable';
           import { Subscription } from 'rxjs/Subscription';
  
           import { IProduct } from './product';
           import { ProductService } from './product.service';
  
           import { NumberValidators } from '../shared/number.validator';
           import { GenericValidator } from '../shared/generic-validator';
  
    @Component({
        templateUrl: './product-edit.component.html'
     })
    export class ProductEditComponent implements OnInit, AfterViewInit, OnDestroy {
      @ViewChildren(FormControlName, { read: ElementRef }) formInputElements: ElementRef[];
  
  pageTitle: string = 'Product Edit';
  errorMessage: string;
  productForm: FormGroup;
  
  product: IProduct;
  private sub: Subscription;
  
  // Use with the generic validation message class
  displayMessage: { [key: string]: string } = {};
  private validationMessages: { [key: string]: { [key: string]: string } };
  private genericValidator: GenericValidator;
  
  get tags(): FormArray {
      return &lt;FormArray&gt;this.productForm.get('tags');
  }
  
  constructor(private fb: FormBuilder,
              private route: ActivatedRoute,
              private router: Router,
              private productService: ProductService) {
  
      // Defines all of the validation messages for the form.
      // These could instead be retrieved from a file or database.
      this.validationMessages = {
          productName: {
              required: 'Product name is required.',
              minlength: 'Product name must be at least three characters.',
              maxlength: 'Product name cannot exceed 50 characters.'
          },
          productCode: {
              required: 'Product code is required.'
          },
          starRating: {
              range: 'Rate the product between 1 (lowest) and 5 (highest).'
          }
      };
  
      // Define an instance of the validator for use with this form, 
      // passing in this form's set of validation messages.
      this.genericValidator = new GenericValidator(this.validationMessages);
  }
  
  ngOnInit(): void {
      this.productForm = this.fb.group({
          productName: ['', [Validators.required,
                             Validators.minLength(3),
                             Validators.maxLength(50)]],
          productCode: ['', Validators.required],
          starRating: ['', NumberValidators.range(1, 5)],
          tags: this.fb.array([]),
          description: ''
      });
  
      // Read the product Id from the route parameter
      this.sub = this.route.params.subscribe(
          params =&gt; {
              let id = +params['id'];
              this.getProduct(id);
          }
      );
  }
  
  ngOnDestroy(): void {
      this.sub.unsubscribe();
  }
  
  ngAfterViewInit(): void {
      // Watch for the blur event from any input element on the form.
      let controlBlurs: Observable&lt;any&gt;[] = this.formInputElements
          .map((formControl: ElementRef) =&gt; Observable.fromEvent(formControl.nativeElement, 'blur'));
  
      // Merge the blur event observable with the valueChanges observable
      Observable.merge(this.productForm.valueChanges, ...controlBlurs).debounceTime(800).subscribe(value =&gt; {
          this.displayMessage = this.genericValidator.processMessages(this.productForm);
      });
  }
  
  addTag(): void {
      this.tags.push(new FormControl());
  }
  
  getProduct(id: number): void {
      this.productService.getProduct(id)
          .subscribe(
              (product: IProduct) =&gt; this.onProductRetrieved(product),
              (error: any) =&gt; this.errorMessage = &lt;any&gt;error
          );
  }
  
  onProductRetrieved(product: IProduct): void {
      if (this.productForm) {
          this.productForm.reset();
      }
      this.product = product;
  
      if (this.product.id === 0) {
          this.pageTitle = 'Add Product';
      } else {
          this.pageTitle = `Edit Product: ${this.product.productName}`;
      }
  
      // Update the data on the form
      this.productForm.patchValue({
          productName: this.product.productName,
          productCode: this.product.productCode,
          starRating: this.product.starRating,
          description: this.product.description
      });
      this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
  }
  
  deleteProduct(): void {
      if (this.product.id === 0) {
          // Don't delete, it was never saved.
          this.onSaveComplete();
     } else {
          if (confirm(`Really delete the product: ${this.product.productName}?`)) {
              this.productService.deleteProduct(this.product.id)
                  .subscribe(
                      () =&gt; this.onSaveComplete(),
                      (error: any) =&gt; this.errorMessage = &lt;any&gt;error
                  );
          }
      }
  }
  
  saveProduct(): void {
      if (this.productForm.dirty &amp;&amp; this.productForm.valid) {
          // Copy the form values over the product object values
          let p = Object.assign({}, this.product, this.productForm.value);
  
          this.productService.saveProduct(p)
              .subscribe(
                  () =&gt; this.onSaveComplete(),
                  (error: any) =&gt; this.errorMessage = &lt;any&gt;error
              );
      } else if (!this.productForm.dirty) {
          this.onSaveComplete();
      }
  }
  
  onSaveComplete(): void {
      // Reset the form to clear the flags
      this.productForm.reset();
      this.router.navigate(['/products']);
     }
   }
  </code></pre>
  
  <p>I am trying to solve this problem for more than 2 days but I still do not have a solution. I have seen many other answers in stackoverflow but none of them is solving my problem.</p>