I am a newbie in Angular and following an online course using Angular 10 but stuck at one point. I am trying to implement the Reactive forms.
For that, I have added a new component text-input. The code for the text-input.component.ts
is as follows:
import { Component, Input, Self } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms';
@Component({
selector: 'app-text-input',
templateUrl: './text-input.component.html',
styleUrls: ['./text-input.component.css']
})
// We need to implement a control value accessor
export class TextInputComponent implements ControlValueAccessor {
@Input() label: string;
@Input() type = 'text';
constructor(@Self() public ngControl: NgControl) {
this.ngControl.valueAccessor = this;
}
writeValue(obj: any): void {
}
registerOnChange(fn: any): void {
}
registerOnTouched(fn: any): void {
}
}
Here is the code for the text-input.component.html
<div class="form-group">
<input [class.is-invalid]="ngControl.touched && ngControl.invalid" type="{{type}}"
class="form-control"
[formControl]="ngControl.control" placeholder="{{label}}">
<div *ngIf='ngControl.control.errors?.required' class="invalid-feedback">Please enter a {{label}}</div>
<div *ngIf='ngControl.control.errors?.minlength'
class="invalid-feedback">{{label}} must be at least {{ngControl.control.errors.minlength['requiredLength']}}</div>
<div *ngIf='ngControl.control.errors?.maxlength' class="invalid-feedback">{{label}} must be at most {{ngControl.control.errors.maxlength['requiredLength']}}</div>
<div *ngIf='ngControl.control.errors?.isMatching' class="invalid-feedback">
Password do not match</div>
</div>
But as soon as I add the code [formControl]
I start getting the error:
Type 'AbstractControl' is missing the following properties from type 'FormControl': registerOnChange, registerOnDisabledChange, _applyFormState
4 [formControl]="ngControl.control" placeholder="{{label}}">
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/app/_forms/text-input/text-input.component.ts:6:16
6 templateUrl: './text-input.component.html',
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component TextInputComponent.
The course Instructor is trying to generate the input controls inside a register component using this component, the code looks like this in register.component.html
<form [formGroup]="registerForm" (ngSubmit)="register()" autocomplete="off">
<h2 class="text-center text-primary">Sign up</h2>
<hr>
<app-text-input [formControl]='registerForm.controls["username"]' [label]='"Username"'></app-text-input>
<div class="form-group text-center">
<button class="btn btn-dark mr-2" type="submit">Register</button>
<button class="btn btn-success mr-2" (click)="cancel()" type="button">Cancel</button>
</div>
</form>
And there is a glimpse of register.component.ts
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { AbstractControl, FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';
import { AccountService } from '../_services/account.service';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
@Output() cancelRegister = new EventEmitter();
model: any = {};
registerForm: FormGroup;
constructor(private accountService: AccountService, private toastr: ToastrService, private fb: FormBuilder) { }
ngOnInit(): void {
this.intitializeForm();
}
intitializeForm() {
this.registerForm = this.fb.group({
username: ['', Validators.required]
})
}
register = () => {
console.log(this.registerForm.value);
}
}
Please do let me know what else you need, being new to Angular I am not able to find the route cause, but if you help me out then I shall move further with my course and would really thankful.
A form control is a user interface control that serves as the point of connection between the user and the server. Interactions vary by control type: buttons: button file handling: input type="file" menus: select , etc.
We do not have a name to the FormGroup . The Index of the element is automatically assigned as the name for the element. Hence we use the [formGroupName]="i" where i is the index of the FormArray to bind the FormGroup to the div element. Finally, we add the controls using the formControlName directive.
There are various suggestions here to cast your AbstractControl
to FormControl
. You can also replace the reference in the template with e.g. [formControl]="$any(ngControl.control)"
. The $any()
cast operator is the only built in casting operator I could find for the templating engine today.
If this bothers you, please go upvote and subscribe to this extremely popular, longstanding issue that could actually provide a decent fix.
It's a problem with the "cast". You can create a getter (it's very similar when we mannage a FormArray, that we create a getter casting a FormArray)
get control(){
return this.ngControl.control as FormControl
}
And replace in your .html all the ngControl.control
by control
Are you using Angular 11 in strict mode here? If so change your tsconfig.json file and set:
"strictTemplates": false
and ignore the error for "Some language features are not available".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With