No provider for ControlContainer and No provider for ControlContainer
Import both Forms Module and ReactiveFormsModule from @angular/forms in the file app.module.ts
Related videos on Youtube
Dea
Updated on June 04, 2022Comments
-
Dea almost 2 years
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.
-
R. Richards about 7 yearsHave you properly imported the FormModule and ReactiveFormsModule in your main application module, or other appropriate module?
-
-
Robert Smith about 4 yearsAnd if this is a tabbed application import in tab1.module.ts