0
votes

So, i'm creating a custom directive and need to use form-controls into it. But i'm getteng an error: No provider for NgControl; I know that the right answer is: import reactive forms module but i've already imported !

import { Directive, ElementRef, Input, HostListener, OnDestroy } from '@angular/core';
import { NgControl } from '@angular/forms'
@Directive({
  selector: '[testDirective]'
})
export class TestDirectiveClass implements OnDestroy{

  constructor(private elementRef: ElementRef, c: NgControl ) { }

    ngOnDestroy() {

  }

}

my component:

<p testDirective>
  Start editing to see some magic happen :)
</p>

and my appModule:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TestDirectiveClass } from './testDirective.directive';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule, ReactiveFormsModule ],
  declarations: [ AppComponent, HelloComponent, TestDirectiveClass ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

my stackblitz

2

2 Answers

1
votes

The exception is being thrown, because the p element missing the [formControlName] directive. The next thing is to use HTML form elements, like input, select, radio button, etc. This is because Angular defines ControlValueAccessor for the default form elements, while p is used only for representation of text, it doesn't have abilities like an input.

app.component.html

<div [formGroup]="form">
  <input testDirective formControlName="testControl">
    Start editing to see some magic happen :)
</div>

app.component.ts

import { Component, VERSION, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, FormControl } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  implements OnInit{
  name = 'Angular ' + VERSION.major;

  form: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.form = this.fb.group({
      testControl: [null]
    })
  }
}

Also the Angular documentation says the following:

A base class that all control FormControl-based directives extend. It binds a FormControl object to a DOM element.

0
votes

You can add Decorator @Optional.

Parameter decorator to be used on constructor parameters, which marks the parameter as being an optional dependency. The DI framework provides null if the dependency is not found.

import { Directive, Optional, ElementRef, Input, HostListener, OnDestroy } from '@angular/core';
import { NgControl } from '@angular/forms'
@Directive({
  selector: '[testDirective]'
})
export class TestDirectiveClass implements OnDestroy{

  constructor(
    @Optional() public c: NgControl,
   private elementRef: ElementRef  ) { }
  
  ngOnDestroy() {
    
  }

}

https://stackblitz.com/edit/angular-ivy-sjr7q7