An attribute directive can be created to automatically add the required
attribute to an element based on the presence of the Validators.required
validator in the corresponding form control:
import { Directive, ElementRef, OnInit } from '@angular/core';
import { FormControlName, NgControl, Validators } from '@angular/forms';
@Directive({
selector: '[formControl], [formControlName]',
standalone: true,
})
export class FormControlRequiredAttributeDirective implements OnInit {
constructor(private elementRef: ElementRef, private ngControl: NgControl) {}
ngOnInit(): void {
if (
(this.ngControl instanceof FormControlName || this.ngControl instanceof FormControlDirective) &&
this.ngControl.control.hasValidator(Validators.required)
) {
this.elementRef.nativeElement.required = 'true';
}
}
}
Simply importing and using this directive in your component will apply the functionality:
@Component({
imports: [ReactiveFormsModule, FormControlRequiredAttributeDirective],
// ...
})
class LoginFormComponent {
formGroup: FormGroup = new FormGroup({
email: new FormControl('', Validators.required),
});
}
<form [formGroup]="formGroup">
<label>
<span>Email</span>
<input type="email" formControlName="email" />
</label>
</form>
By following this approach, you ensure that validators are the sole source of truth, reducing repetition in your code.