Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 1x 227x 227x 227x 1x 73x 73x 1x 154x 154x 40x 40x 154x | import type { Signal } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
import type { AbstractControl, ValidationErrors } from '@angular/forms';
import { PASSWORDS } from '~/app/shared/constants';
import { controlErrorsSignal } from '~/app/shared/control-errors-signal.util';
import { controlInvalidSignal } from '~/app/shared/control-invalid-signal.util';
import { passwordFirebaseValidator, passwordStrengthValidator } from './validators/passwords';
/**
* Pair control with Angular Signals for handling validation in the template.
*/
const getControlStructure = <T extends AbstractControl>(control: T): ControlStruct<T> => {
const $invalid = controlInvalidSignal(control);
const $errors = controlErrorsSignal(control);
return { $errors, $invalid, control };
};
export { PASSWORDS };
/**
* For each Identity Control generate two Signals for error handling.
*/
export interface ControlStruct<T extends AbstractControl = FormControl> {
/** Returns errors for the control, but only when the control is dirty. */
readonly $errors: Signal<ValidationErrors | undefined>;
/** Flag for aria-invalid, but only when the control is modified, invalid, and interacted with. */
readonly $invalid: Signal<boolean>;
/** Identity control. */
readonly control: T;
}
/**
* Emails are required and must be a valid email address.
*/
export const createEmailControl = (): ControlStruct<FormControl> => {
// eslint-disable-next-line unicorn/no-null -- DOM forms use null
const control = new FormControl<string | null>(null, [ Validators.required, Validators.email ]);
return getControlStructure(control);
};
/**
* Passwords are required and have length requirements. Complexity is required for new password fields.
* @param isNewPassword - Adds extra validators to control when being used to create a new password.
* Note: this should only be used on the first password field, not the confirm
* field.
*/
export const createPasswordControl = (isNewPassword: boolean = false): ControlStruct<FormControl> => {
const control = new FormControl<string | null>(
null, // eslint-disable-line unicorn/no-null -- DOM forms use null
[
Validators.required,
Validators.minLength(PASSWORDS.minLength),
Validators.maxLength(PASSWORDS.maxLength),
],
);
if (isNewPassword) {
control.addValidators(passwordStrengthValidator);
control.addAsyncValidators(passwordFirebaseValidator());
}
return getControlStructure(control);
};
|