Step by step.
When we make a custom form control with validate the function validate should return or an object or null -if no errors-.
public validate(c: FormControl) { const errors: any[] = []; if (!this.control) this.control = c; this.errors && this.errors.forEach((error) => { if (error.type == 'required') { if (!c.value) { errors.push({ required: true, message: error.message }); } } }); return errors.length ? { error: errors } : null; }
See that return an object with an unique property "error" that is an array of errors.
This error is an error not of the inner control -you input inside the custom-input- else the FormControl declared in "parent". So, to iterate over this error inside the custom form control we need "get it".
Generally you use the constructor
constructor(@Optional() @Self() public ngControl: NgControl){ if (this.ngControl != null) { this.ngControl.valueAccessor = this; } }
But, as we have a validate function simply we declare, and give value to it in validate function
control!: AbstractControl; public validate(c: FormControl) { if (!this.control) this.control = c; ...rest of the code.. }
The last is iterate over this errors
<ng-container *ngIf="control?.touched || control?.dirty"> <ng-container *ngFor="let error of control?.errors?.error"> <div class="error-text"> {{ error.message }} </div> </ng-container> </ng-container>
Your forked stackblitz
NOTE: See that you needn't add the validators to your FormControls
In your code:
registrationForm = this.fb.group({ username: [''], password: [''], });
update to only send if reuired we need use some like
public validate(c: FormControl) { const errors: any[] = []; if (!this.control) this.control = c; cons errorRequired==!c.value && this.errors?this.errors.find(x=>x=='required'):null if (errorRequired) return [{required:true,message:errorRequired.message}] this.errors && this.errors.forEach((error) => { if (error.type == 'required') { if (!c.value) { errors.push({ required: true, message: error.message }); } } }); return errors.length ? { error: errors } : null;