Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No provider for ControlContainer and No provider for ControlContainer

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 :

The first error is about NgControl as below:

No provider for NgControl ("

div class="col-md-8" [ERROR ->]input class="form-control" id="productNameId" "): ProductEditComponent@16:24

The second error is about ControlContainer as below:

No provider for ControlContainer (" div [ERROR ->]div formArrayName="tags">

div class="row">

button cl"):

Htmm file is as below:

 <div class="panel panel-primary">
   <div class="panel-heading">
      {{pageTitle}}
</div>

<div class="panel-body">
    <form class="form-horizontal"
          novalidate
          (ngSubmit)="saveProduct()"
          formGroup="productForm" >
        <fieldset>
            <div class="form-group" 
                 [ngClass]="{'has-error': displayMessage.productName }">
                <label class="col-md-2 control-label" for="productNameId">Product Name</label>

                <div class="col-md-8">
                    <input class="form-control" 
                            id="productNameId" 
                            type="text" 
                            placeholder="Name (required)" 
                            formControlName="productName" />
                    <span class="help-block" *ngIf="displayMessage.productName">
                            {{displayMessage.productName}}
                    </span>
                </div>
            </div>


 <div formArrayName="tags">
                <div class="row">
                    <button class="col-md-offset-1 col-md-1 btn btn-default"
                            type="button"
                            (click)="addTag()">Add Tag
                    </button>
                </div>
                <div class="form-group"
                    *ngFor="let tag of tags.controls; let i=index" >
                    <label class="col-md-2 control-label" [attr.for]="i">Tag</label>

                    <div class="col-md-8">
                        <input class="form-control" 
                                [id]="i" 
                                type="text" 
                                placeholder="Tag" 
                                formControlName="i" />
                    </div>
                </div>
            </div>
    <!--more piece of code here -->

My component file is as below:

         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 <FormArray>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 => {
            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<any>[] = this.formInputElements
        .map((formControl: ElementRef) => Observable.fromEvent(formControl.nativeElement, 'blur'));

    // Merge the blur event observable with the valueChanges observable
    Observable.merge(this.productForm.valueChanges, ...controlBlurs).debounceTime(800).subscribe(value => {
        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) => this.onProductRetrieved(product),
            (error: any) => this.errorMessage = <any>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(
                    () => this.onSaveComplete(),
                    (error: any) => this.errorMessage = <any>error
                );
        }
    }
}

saveProduct(): void {
    if (this.productForm.dirty && 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(
                () => this.onSaveComplete(),
                (error: any) => this.errorMessage = <any>error
            );
    } else if (!this.productForm.dirty) {
        this.onSaveComplete();
    }
}

onSaveComplete(): void {
    // Reset the form to clear the flags
    this.productForm.reset();
    this.router.navigate(['/products']);
   }
 }

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.

like image 367
Dea Avatar asked Mar 21 '17 23:03

Dea


People also ask

What is ControlContainer in angular?

The ControlContainer is a base class for form directives that contain multiple registered instances of NgControl. We can use the ControlContainer to access FormControls, FormGroups, and FormArrays and manage a main form chunked across components.

What is NgModelGroup?

The NgModelGroup is used to create a top-level form group Instance, and it binds the form to the given form value. Syntax: <div ngModelGroup="name"></div> NgModule: Module used by NgModelGroup is: FormsModule.

Can't bind to formGroup since it isn't a known property of?

What Does This Error Mean? Angular is trying to tell us that it doesn't know about the formGroup directive on the <form> element in your component. This usually happens when the wrong forms module is imported, the right module is imported in the wrong place or the ReactiveFormsModule is just not imported at all.


1 Answers

Import both Forms Module and ReactiveFormsModule from @angular/forms in the file app.module.ts

like image 103
Ayushi Jain Avatar answered Nov 07 '22 05:11

Ayushi Jain