I'm creating a custom angular component which shows an error tooltip when my FormControl (Reactive Forms) is invalid. But I don't know how I can access the FormControl inside my custom component to check whether or not it is marked as valid.
What I want to accomplish
<div [formGroup]="form">
<input formControlName="name" type="text" />
<custom-validation-message formControlName="name">My special error message!</custom-validation-message>
</div>
Already encountered stuff
ERROR Error: No value accessor for form control with name: 'surveyType'
Fixed this by implementing ControlValueAccessor with NG_VALUE_ACCESSOR even though I don't want to alter the value. I also added an injector to access the NgControl.
import { Component, OnInit, Injector } from '@angular/core';
import { NgControl, ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'custom-validation-message',
templateUrl: './validation-message.component.html',
providers: [{
provide: NG_VALUE_ACCESSOR, multi: true, useExisting: ValidationMessageComponent
}]
})
export class ValidationMessageComponent implements ControlValueAccessor, OnInit {
public formControl: any;
constructor(private injector: Injector) {
super();
}
public ngOnInit(): void {
const model = this.injector.get(NgControl);
this.formControl = model.control;
}
public writeValue(obj: any): void {
}
public registerOnChange(fn: any): void {
}
public registerOnTouched(fn: any): void {
}
public setDisabledState?(isDisabled: boolean): void {
}
}
Current Problem The model.control is undefined. After inspecting the model I found out that the model is as good as empty only the _parent is a full representation of my form. The model._parent.controls does contain all the controls of my form. But still I don't know the current control.
To fetch the value of a form control, we have to use value property on the instance of FormControl in our class. In the same way we can fetch the value in HTML template. city = new FormControl('Noida'); console. log(this.
as I get you point you just want to make a componnet for display form control validation message the other answer explane why ControlValueAccessor is not the case here ,you just want to pass a control form reference to the component then check the validation state , Thomas Schneiter answer is a correct why but I face the case and it 's hard to keep get refrance by get method and sometime we are in sub group and form array so I idea is to just pass the name of the form control as string then get the control reference.
CustomValidationMessageComponent
@Component({
selector: "custom-validation-message",
templateUrl: "./custom-validation-message.component.html",
styleUrls: ["./custom-validation-message.component.css"]
})
export class CustomValidationMessageComponent {
@Input()
public controlName: string;
constructor(@Optional() private controlContainer: ControlContainer) {}
get form(): FormGroup {
return this.controlContainer.control as FormGroup;
}
get control(): FormControl {
return this.form.get(this.controlName) as FormControl;
}
}
template
<ng-container *ngIf="control && control?.invalid && control?.touched">
<ul>
<li *ngIf="control.hasError('required')">
this is required field
</li>
<li *ngIf="control.hasError('pattern')">
pattern is invalid
</li>
<li *ngIf="control.hasError('maxlength')">
the length is over the max limit
</li>
<!-- <li *ngFor="let err of control.errors | keyvalue">
{{err.key}}
</li> -->
</ul>
</ng-container>
and you can use it like this
<form [formGroup]="form">
<label>
First Name <input type="text" formControlName="firstName" />
<div>
<custom-validation-message controlName="firstName"></custom-validation-message>
</div>
</label>
...
</form>
demo 🚀🚀
you can check this angular library ngx-valdemort created by JB Nizet where it solve this problem perfectly 👌.
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