Shubham Sharma
Shubham Sharma

Reputation: 129

'AbstractControl' is missing the following properties from type 'FormControl'

I'm new to angular, and I'm learning reactive forms.

There's this one issue that I'm not able to solve. Here, I'm trying to create a reusable input component for my form. But, there's this Abstractform control error that I'm not able to resolve.

NOTE: I don't wanna use "strictTemplates": false.

Can someone help me understand what's exactly going on here and how can I resolve this error?

Here's the list of files to reproduce the error -

reactive-form.component.ts

import { Component } from '@angular/core'
import { FormGroup, FormControl, Validators } from '@angular/forms'

@Component({
  selector: 'app-reactive-form',
  templateUrl: './reactive-form.component.html',
  styleUrls: ['./reactive-form.component.css'],
})
export class ReactiveFormComponent {
  cardForm = new FormGroup({
    name: new FormControl('', [Validators.required, Validators.minLength(3)]),
  })
}

reactive-form.component.html (Getting error here)

<form [formGroup]="cardForm"></form>

<!--Type 'AbstractControl' is missing the following properties from type 'FormControl': registerOnChange, registerOnDisabledChange, _applyFormState  -->
<app-input [control]="cardForm.controls.name"></app-input>

input.component.ts

import { Component, Input } from '@angular/core'
import { FormControl } from '@angular/forms'

@Component({
  selector: 'app-input',
  templateUrl: './input.component.html',
  styleUrls: ['./input.component.css'],
})
export class InputComponent {
  @Input() control: FormControl = new FormControl()
}

input.component.html

<input [formControl]="control" />
<ng-container *ngIf="control.dirty && control.touched && control.errors">
  <div *ngIf="control.errors.required">Value is required</div>
  <div *ngIf="control.errors.minlength">
    Value should be longer Required min value is
    {{ control.errors.minlength.requiredLength }}
  </div>
</ng-container>

NOTE: I've already analyzed a couple of similar threads but those are hard for me to understand. Will appreciate it if someone can take this example and explain what's wrong here.

Upvotes: 1

Views: 4002

Answers (3)

Eliseo
Eliseo

Reputation: 57929

You can get another aproach that is use a getter in your compoment

control:FormControl=new FormControl();
@Input('control') set _(value)
{
  this.control=value as FormControl;
}

Upvotes: 1

shahab jani
shahab jani

Reputation: 88

Your input component must be like this: ts file:

@Component({
  selector: 'app-input', 
  templateUrl: './input.component.css.html', 
  styleUrls: ['./input.component.css.css'], 
  encapsulation: ViewEncapsulation.None,  
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR] })
export class InputComponent implements ControlValueAccessor,OnChanges{   
InputValue: any;  
@Input() control: FormControl = new FormControl();   
onChange(value) {
    this.propagateChange(value);  
 }   
writeValue(value: any) {
    this.InputValue = value;  
 } 
  registerOnChange(fn: any) 
{
    this.propagateChange = fn;  
 }   
registerOnTouched(fn: any) {
    this.propagateTouched = fn;   
}  
 propagateChange = (_: any) => { }  
 propagateTouched = (_: any) => { } 
}

html file:

<input [(ngModel)]='InputValue' (ngModelChange)="onChange($event)" />
<ng-container *ngIf="control.dirty && control.touched && control.errors">
  <div *ngIf="control.errors.required">Value is required</div>
  <div *ngIf="control.errors.minlength">
    Value should be longer Required min value is
    {{ control.errors.minlength.requiredLength }}
  </div>
</ng-container>
get name() {
    return this.cardForm.get('name');
}
<app-input [control]="name" formControlName="name">
</app-input>

Upvotes: 0

Yong Shun
Yong Shun

Reputation: 51135

You get this error because Angular doesn't know that you are passing FormControl. Instead, Angular treats it as AbstractControl.

Type 'AbstractControl' is missing the following properties from type 'FormControl': registerOnChange, registerOnDisabledChange, _applyFormState


Solution

Add cardFormNameControl getter to specify that you are passing FormControl to InputComponent.

reactive.component.html

export class ReactiveFormComponent {
  ...

  get cardFormNameControl(): FormControl {
    return this.cardForm.get('name') as FormControl;
  }
}
<app-input [control]="cardFormNameControl"></app-input>

Sample solution on StackBlitz

Upvotes: 4

Related Questions