I'm trying to learn about different ways to create custom form control using angular 13.
I've watched the Angular Connect 2017 video regarding angular forms from https://www.youtube.com/watch?v=CD_t3m2WMM8 and tried to implement and custom form control with validators.
i have a form with email and password, i created a custom control for the email,
and none of the validations that i configured are being triggered (required
and email
)
the custom form element is called app-tuxin-form-email-input
that contains it's own form using a form builder.
this is the class:
import {Component, OnInit, Self, SimpleChanges} from '@angular/core';
import {
ControlValueAccessor, FormBuilder, FormGroup,
NgControl,
Validators
} from '@angular/forms';
@Component({
selector: 'app-tuxin-form-email-input',
templateUrl: './tuxin-form-email-input.component.html',
styleUrls: ['./tuxin-form-email-input.component.scss'],
})
export class TuxinFormEmailInputComponent implements ControlValueAccessor, OnInit {
newChildForm: FormGroup;
onChange = (email: string) => {};
onTouched = () => {};
touched = false;
disabled = false;
constructor(private fb: FormBuilder, @Self() public controlDir: NgControl) {
controlDir.valueAccessor=this;
this.newChildForm = this.fb.group({
email: [''],
});
}
writeValue(email: string) {
this.newChildForm.get('email')?.setValue(email, { emitEvent: false });
}
registerOnChange(onChange: any) {
this.onChange = onChange;
}
registerOnTouched(onTouched: any) {
this.onTouched = onTouched;
}
ngOnInit(): void {
const control = this.controlDir.control;
const validators = [Validators.required, Validators.email];
if (control) {
if (control.validator) {
validators.unshift(control.validator);
}
control.setValidators(validators);
control.updateValueAndValidity();
}
}
setDisabledState(disabled: boolean) {
this.disabled = disabled;
disabled ? this.newChildForm.disable() : this.newChildForm.enable();
}
}
and this is the template:
<div [formGroup]="newChildForm">
<mat-form-field>
<mat-label>Email</mat-label>
<input matInput type="email" formControlName="email"
(blur)="onTouched()" (input)="onChange($any($event.target).value)" [disabled]="disabled"
/>
<mat-error i18n *ngIf="controlDir && controlDir.hasError('required')">Email is required</mat-error>
<mat-error i18n *ngIf="controlDir && controlDir.hasError('email')">Email Invalid</mat-error>
</mat-form-field>
</div>
so unfortunately none of the validators errors are being triggers and i can't understand why.
I created a stackblitz for that at https://stackblitz.com/edit/angular-ivy-2s36qf?file=src/app/app.module.ts
any ideas regarding this issue would be greatly apprecaited.
thanks
Using the FormControl object on your child component, and it makes it easier to use
NG_VALUE_ACCESSOR
when you do so.Also the registration of events have a callback which needs to be called for the outer form to be notified of the form changes
I forked your stackblitz and adjusted it accordingly.
The main changes were to:
to have the formControl for the email available as a variable
and to adjust callbacks to the event registration methods
registerOnChange
andregisterOnTouched