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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | 30x 30x 11x 11x 49x 49x 3x 19x 36x 36x 36x 4x 36x 8x | import { FormControl, FormGroup, ValidationErrors, ValidatorFn } from '@angular/forms'; /** * A helper function that transforms the special validators to a formly-usable function. * * @param name the error to be extracted from the validator * @param validator the validator that should be transformed * @returns a function that conforms the type signature formly expects. * * @usageNotes * Refer to the [`FormlyFieldConfig.validators`](https://github.com/ngx-formly/ngx-formly/blob/main/src/core/src/lib/models/fieldconfig.ts#L60) type definition for an explanation of the necessary validator format. * */ export function formlyValidation<T extends (control: FormControl) => { [error: string]: { valid: boolean } }>( name: string, validator: T ): (control: FormControl) => boolean { return c => { const validationResult = validator(c); Iif (!c) { return; } return validationResult?.[name]?.valid ?? true; }; } export class SpecialValidators { /** * password validator: char + numbers, min length 7 */ static password(control: FormControl): { [error: string]: { valid: boolean } } { const passwordPattern = /^(|(?=[^\s]*[a-zA-Z])(?=[^\s]*[\d])[^\s]*)$/; Iif (!control.value) { return; } return passwordPattern.test(control.value) && control.value.length > 6 ? undefined : { password: { valid: false } }; } static noSpecialChars(control: FormControl): { [error: string]: { valid: boolean } } { const noSpecialCharsPattern = /^[^\<\>\&\@\;\%\*\#\|\_\[\]\!\?\~\+\{\}\(\)\:]*$/; return noSpecialCharsPattern.test(control.value) ? undefined : { noSpecialChars: { valid: false } }; } /** * Prevent "<" and ">" to avoid usage of HTML tags. */ static noHtmlTags(control: FormControl): { [error: string]: { valid: boolean } } { const noHtmlTagsPattern = /^[^\<\>]*$/; return noHtmlTagsPattern.test(control.value) ? undefined : { noHtmlTags: { valid: false } }; } static punchoutLogin(control: FormControl): { [error: string]: { valid: boolean } } { const punchoutLoginPattern = /^[a-zA-Z0-9_.@]*$/; return punchoutLoginPattern.test(control.value) ? undefined : { punchoutLogin: { valid: false } }; } static integer(control: FormControl): { [error: string]: { valid: boolean } } { const integerPattern = /^(?:-?(?:0|[1-9][0-9]*)|)$/; return integerPattern.test(control.value) ? undefined : { integer: { valid: false } }; } static email(control: FormControl): { [error: string]: { valid: boolean } } { /* * very simplified email matching * - local part mustn't start or end with dot * - domain mustn't start or end with dash * - no IPs allowed for login emails * - only some special characters allowed */ return /^([\w\-\~\+]+\.)*[\w\-\~\+]+@(([\w][\w\-]*)?[\w]\.)+[a-zA-Z]{2,}$/.test(control.value) ? undefined : { email: { valid: false } }; } static phone(control: FormControl): { [error: string]: { valid: boolean } } { /* * simplified phone matching * - phone number must start with + or digit * - number blocks can be separated with hyphens or spaces * - number blocks can stand in brackets * - phone number must have 7 to 15 digits */ return control.value ? /^((?:\+?\d{7,15})$)|^((\(?\d{3}\)?(?: |-)?){2}\(?\d{3,4}\)?)$/.test(control.value) ? undefined : { phone: { valid: false } } : undefined; } /** * Compare two form controls for equality. * * The Validator has to be attached to the parent form group containing both controls under investigation. * The first argument control name receives the error if controls do not have an equal value. */ static equalTo(errorReceivingControlName: string, compareControlName: string): ValidatorFn { return (group: FormGroup): ValidationErrors => { const errorReceivingControl = group.get(errorReceivingControlName); const otherErrorKeys = Object.keys(errorReceivingControl?.errors || {}).filter(x => x !== 'equalTo'); if (errorReceivingControl && !otherErrorKeys.length) { errorReceivingControl.setErrors( errorReceivingControl.value === group.get(compareControlName)?.value ? undefined : { equalTo: { valid: false } } ); } return []; }; } /** * A form control is required if a related form control is not empty. * * The Validator has to be attached to the parent form group containing both controls under investigation. * The 'dependentlyRequired' error is set for the first argument control name if it is empty but the related control has a value. * */ static dependentlyRequired(requiredControlName: string, relatedControlName: string) { return (group: FormGroup): ValidationErrors => { const requiredControl = group.get(requiredControlName); const relatedControl = group.get(relatedControlName); const otherErrorKeys = Object.keys(requiredControl?.errors || {}).filter(x => x !== 'dependentlyRequired'); Iif (requiredControl && !otherErrorKeys.length) { requiredControl.setErrors( !relatedControl?.value || requiredControl.value ? undefined : { dependentlyRequired: { valid: false } } ); } return []; }; } static moneyAmount(control: FormControl): { [error: string]: { valid: boolean } } { const moneyAmountPattern = /^$|^\d{1,9}(\.\d{1,2})?$/; Iif (!control.value) { return; } return moneyAmountPattern.test(control.value) ? undefined : { moneyAmount: { valid: false } }; } static noSunday(control: FormControl): boolean { return SpecialValidators.noDay(control, 'sunday'); } static noSaturday(control: FormControl): boolean { return SpecialValidators.noDay(control, 'saturday'); } private static noDay(control: FormControl, day: 'saturday' | 'sunday'): boolean { const date = control.value as Date; return !(day === 'saturday' ? date?.getDay() === 6 : date?.getDay() === 0); } } |