@ng-formworks/core 17.2.7 → 17.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +836 -0
  3. package/esm2022/lib/framework-library/framework-library.service.mjs +175 -0
  4. package/esm2022/lib/framework-library/framework.mjs +15 -0
  5. package/esm2022/lib/framework-library/no-framework.component.mjs +18 -0
  6. package/esm2022/lib/framework-library/no-framework.module.mjs +27 -0
  7. package/esm2022/lib/framework-library/no.framework.mjs +19 -0
  8. package/esm2022/lib/json-schema-form.component.mjs +765 -0
  9. package/esm2022/lib/json-schema-form.module.mjs +26 -0
  10. package/esm2022/lib/json-schema-form.service.mjs +679 -0
  11. package/esm2022/lib/locale/de-validation-messages.mjs +60 -0
  12. package/esm2022/lib/locale/en-validation-messages.mjs +60 -0
  13. package/esm2022/lib/locale/es-validation-messages.mjs +57 -0
  14. package/esm2022/lib/locale/fr-validation-messages.mjs +60 -0
  15. package/esm2022/lib/locale/index.mjs +8 -0
  16. package/esm2022/lib/locale/it-validation-messages.mjs +60 -0
  17. package/esm2022/lib/locale/pt-validation-messages.mjs +60 -0
  18. package/esm2022/lib/locale/zh-validation-messages.mjs +60 -0
  19. package/esm2022/lib/shared/convert-schema-to-draft6.function.mjs +300 -0
  20. package/esm2022/lib/shared/form-group.functions.mjs +442 -0
  21. package/esm2022/lib/shared/format-regex.constants.mjs +54 -0
  22. package/esm2022/lib/shared/index.mjs +12 -0
  23. package/esm2022/lib/shared/json-schema.functions.mjs +784 -0
  24. package/esm2022/lib/shared/json.validators.mjs +884 -0
  25. package/esm2022/lib/shared/jsonpointer.functions.mjs +1026 -0
  26. package/esm2022/lib/shared/layout.functions.mjs +1154 -0
  27. package/esm2022/lib/shared/merge-schemas.function.mjs +345 -0
  28. package/esm2022/lib/shared/utility.functions.mjs +380 -0
  29. package/esm2022/lib/shared/validator.functions.mjs +584 -0
  30. package/esm2022/lib/widget-library/add-reference.component.mjs +61 -0
  31. package/esm2022/lib/widget-library/button.component.mjs +72 -0
  32. package/esm2022/lib/widget-library/checkbox.component.mjs +105 -0
  33. package/esm2022/lib/widget-library/checkboxes.component.mjs +147 -0
  34. package/esm2022/lib/widget-library/file.component.mjs +35 -0
  35. package/esm2022/lib/widget-library/hidden.component.mjs +54 -0
  36. package/esm2022/lib/widget-library/index.mjs +55 -0
  37. package/esm2022/lib/widget-library/input.component.mjs +119 -0
  38. package/esm2022/lib/widget-library/message.component.mjs +38 -0
  39. package/esm2022/lib/widget-library/none.component.mjs +21 -0
  40. package/esm2022/lib/widget-library/number.component.mjs +123 -0
  41. package/esm2022/lib/widget-library/one-of.component.mjs +35 -0
  42. package/esm2022/lib/widget-library/orderable.directive.mjs +123 -0
  43. package/esm2022/lib/widget-library/radios.component.mjs +153 -0
  44. package/esm2022/lib/widget-library/root.component.mjs +79 -0
  45. package/esm2022/lib/widget-library/section.component.mjs +199 -0
  46. package/esm2022/lib/widget-library/select-framework.component.mjs +51 -0
  47. package/esm2022/lib/widget-library/select-widget.component.mjs +46 -0
  48. package/esm2022/lib/widget-library/select.component.mjs +150 -0
  49. package/esm2022/lib/widget-library/submit.component.mjs +82 -0
  50. package/esm2022/lib/widget-library/tab.component.mjs +41 -0
  51. package/esm2022/lib/widget-library/tabs.component.mjs +108 -0
  52. package/esm2022/lib/widget-library/template.component.mjs +46 -0
  53. package/esm2022/lib/widget-library/textarea.component.mjs +104 -0
  54. package/esm2022/lib/widget-library/widget-library.module.mjs +42 -0
  55. package/esm2022/lib/widget-library/widget-library.service.mjs +226 -0
  56. package/esm2022/ng-formworks-core.mjs +5 -0
  57. package/esm2022/public_api.mjs +13 -0
  58. package/fesm2022/ng-formworks-core.mjs +10149 -0
  59. package/fesm2022/ng-formworks-core.mjs.map +1 -0
  60. package/index.d.ts +5 -0
  61. package/lib/framework-library/framework-library.service.d.ts +55 -0
  62. package/lib/framework-library/framework.d.ts +13 -0
  63. package/lib/framework-library/no-framework.component.d.ts +8 -0
  64. package/lib/framework-library/no-framework.module.d.ts +9 -0
  65. package/lib/framework-library/no.framework.d.ts +10 -0
  66. package/lib/json-schema-form.component.d.ts +218 -0
  67. package/lib/json-schema-form.module.d.ts +11 -0
  68. package/lib/json-schema-form.service.d.ts +115 -0
  69. package/lib/locale/de-validation-messages.d.ts +1 -0
  70. package/lib/locale/en-validation-messages.d.ts +1 -0
  71. package/lib/locale/es-validation-messages.d.ts +1 -0
  72. package/lib/locale/fr-validation-messages.d.ts +1 -0
  73. package/{src/lib/locale/index.ts → lib/locale/index.d.ts} +7 -7
  74. package/lib/locale/it-validation-messages.d.ts +1 -0
  75. package/lib/locale/pt-validation-messages.d.ts +1 -0
  76. package/lib/locale/zh-validation-messages.d.ts +1 -0
  77. package/lib/shared/convert-schema-to-draft6.function.d.ts +21 -0
  78. package/lib/shared/form-group.functions.d.ts +100 -0
  79. package/lib/shared/format-regex.constants.d.ts +19 -0
  80. package/lib/shared/index.d.ts +9 -0
  81. package/lib/shared/json-schema.functions.d.ts +193 -0
  82. package/lib/shared/json.validators.d.ts +441 -0
  83. package/lib/shared/jsonpointer.functions.d.ts +416 -0
  84. package/lib/shared/layout.functions.d.ts +83 -0
  85. package/lib/shared/merge-schemas.function.d.ts +19 -0
  86. package/lib/shared/utility.functions.d.ts +165 -0
  87. package/{src/lib/shared/validator.functions.ts → lib/shared/validator.functions.d.ts} +364 -601
  88. package/lib/widget-library/add-reference.component.d.ts +20 -0
  89. package/lib/widget-library/button.component.d.ts +21 -0
  90. package/lib/widget-library/checkbox.component.d.ts +24 -0
  91. package/lib/widget-library/checkboxes.component.d.ts +24 -0
  92. package/lib/widget-library/file.component.d.ts +21 -0
  93. package/lib/widget-library/hidden.component.d.ts +19 -0
  94. package/{src/lib/widget-library/index.ts → lib/widget-library/index.d.ts} +47 -56
  95. package/lib/widget-library/input.component.d.ts +22 -0
  96. package/lib/widget-library/message.component.d.ts +15 -0
  97. package/lib/widget-library/none.component.d.ts +8 -0
  98. package/lib/widget-library/number.component.d.ts +25 -0
  99. package/lib/widget-library/one-of.component.d.ts +21 -0
  100. package/lib/widget-library/orderable.directive.d.ts +41 -0
  101. package/lib/widget-library/radios.component.d.ts +23 -0
  102. package/lib/widget-library/root.component.d.ts +17 -0
  103. package/lib/widget-library/section.component.d.ts +19 -0
  104. package/lib/widget-library/select-framework.component.d.ts +18 -0
  105. package/lib/widget-library/select-widget.component.d.ts +18 -0
  106. package/lib/widget-library/select.component.d.ts +24 -0
  107. package/lib/widget-library/submit.component.d.ts +24 -0
  108. package/lib/widget-library/tab.component.d.ts +14 -0
  109. package/lib/widget-library/tabs.component.d.ts +20 -0
  110. package/lib/widget-library/template.component.d.ts +18 -0
  111. package/lib/widget-library/textarea.component.d.ts +21 -0
  112. package/lib/widget-library/widget-library.module.d.ts +31 -0
  113. package/lib/widget-library/widget-library.service.d.ts +22 -0
  114. package/package.json +64 -53
  115. package/{src/public_api.ts → public_api.d.ts} +9 -21
  116. package/karma.conf.js +0 -46
  117. package/ng-package.json +0 -11
  118. package/src/lib/framework-library/framework-library.service.ts +0 -195
  119. package/src/lib/framework-library/framework.ts +0 -11
  120. package/src/lib/framework-library/no-framework.component.html +0 -2
  121. package/src/lib/framework-library/no-framework.component.ts +0 -11
  122. package/src/lib/framework-library/no-framework.module.ts +0 -18
  123. package/src/lib/framework-library/no.framework.ts +0 -11
  124. package/src/lib/json-schema-form.component.html +0 -7
  125. package/src/lib/json-schema-form.component.ts +0 -809
  126. package/src/lib/json-schema-form.module.ts +0 -17
  127. package/src/lib/json-schema-form.service.ts +0 -907
  128. package/src/lib/locale/de-validation-messages.ts +0 -58
  129. package/src/lib/locale/en-validation-messages.ts +0 -58
  130. package/src/lib/locale/es-validation-messages.ts +0 -55
  131. package/src/lib/locale/fr-validation-messages.ts +0 -58
  132. package/src/lib/locale/it-validation-messages.ts +0 -58
  133. package/src/lib/locale/pt-validation-messages.ts +0 -58
  134. package/src/lib/locale/zh-validation-messages.ts +0 -58
  135. package/src/lib/locale-dates/en-US.ts +0 -5
  136. package/src/lib/shared/convert-schema-to-draft6.function.ts +0 -321
  137. package/src/lib/shared/form-group.functions.ts +0 -522
  138. package/src/lib/shared/format-regex.constants.ts +0 -73
  139. package/src/lib/shared/index.ts +0 -40
  140. package/src/lib/shared/json-schema.functions.ts +0 -788
  141. package/src/lib/shared/json.validators.ts +0 -878
  142. package/src/lib/shared/jsonpointer.functions.ts +0 -1012
  143. package/src/lib/shared/jspointer.functions.json.spec.ts +0 -103
  144. package/src/lib/shared/layout.functions.ts +0 -1233
  145. package/src/lib/shared/merge-schemas.function.ts +0 -329
  146. package/src/lib/shared/utility.functions.ts +0 -373
  147. package/src/lib/shared/validator.functions.spec.ts +0 -55
  148. package/src/lib/widget-library/add-reference.component.ts +0 -59
  149. package/src/lib/widget-library/button.component.ts +0 -54
  150. package/src/lib/widget-library/checkbox.component.ts +0 -74
  151. package/src/lib/widget-library/checkboxes.component.ts +0 -104
  152. package/src/lib/widget-library/file.component.ts +0 -36
  153. package/src/lib/widget-library/hidden.component.ts +0 -39
  154. package/src/lib/widget-library/input.component.ts +0 -76
  155. package/src/lib/widget-library/message.component.ts +0 -29
  156. package/src/lib/widget-library/none.component.ts +0 -12
  157. package/src/lib/widget-library/number.component.ts +0 -79
  158. package/src/lib/widget-library/one-of.component.ts +0 -36
  159. package/src/lib/widget-library/orderable.directive.ts +0 -130
  160. package/src/lib/widget-library/radios.component.ts +0 -101
  161. package/src/lib/widget-library/root.component.ts +0 -78
  162. package/src/lib/widget-library/section.component.ts +0 -133
  163. package/src/lib/widget-library/select-framework.component.ts +0 -50
  164. package/src/lib/widget-library/select-widget.component.ts +0 -46
  165. package/src/lib/widget-library/select.component.ts +0 -96
  166. package/src/lib/widget-library/submit.component.ts +0 -68
  167. package/src/lib/widget-library/tab.component.ts +0 -29
  168. package/src/lib/widget-library/tabs.component.ts +0 -83
  169. package/src/lib/widget-library/template.component.ts +0 -52
  170. package/src/lib/widget-library/textarea.component.ts +0 -68
  171. package/src/lib/widget-library/widget-library.module.ts +0 -13
  172. package/src/lib/widget-library/widget-library.service.ts +0 -234
  173. package/src/test.ts +0 -18
  174. package/tsconfig.lib.json +0 -25
  175. package/tsconfig.lib.prod.json +0 -9
  176. package/tsconfig.spec.json +0 -17
  177. package/tslint.json +0 -11
@@ -1,878 +0,0 @@
1
- import isEqual from 'lodash/isEqual';
2
- import {
3
- _executeAsyncValidators,
4
- _executeValidators,
5
- _mergeErrors,
6
- _mergeObjects,
7
- AsyncIValidatorFn,
8
- getType,
9
- hasValue,
10
- isArray,
11
- isBoolean,
12
- isDefined,
13
- isEmpty,
14
- isNumber,
15
- isString,
16
- isType,
17
- IValidatorFn,
18
- SchemaPrimitiveType,
19
- toJavaScriptType,
20
- toObservable,
21
- xor
22
- } from './validator.functions';
23
- import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
24
- import { forEachCopy } from './utility.functions';
25
- import { forkJoin } from 'rxjs';
26
- import { JsonSchemaFormatNames, jsonSchemaFormatTests } from './format-regex.constants';
27
- import { map } from 'rxjs/operators';
28
-
29
-
30
-
31
- /**
32
- * 'JsonValidators' class
33
- *
34
- * Provides an extended set of validators to be used by form controls,
35
- * compatible with standard JSON Schema validation options.
36
- * http://json-schema.org/latest/json-schema-validation.html
37
- *
38
- * Note: This library is designed as a drop-in replacement for the Angular
39
- * Validators library, and except for one small breaking change to the 'pattern'
40
- * validator (described below) it can even be imported as a substitute, like so:
41
- *
42
- * import { JsonValidators as Validators } from 'json-validators';
43
- *
44
- * and it should work with existing code as a complete replacement.
45
- *
46
- * The one exception is the 'pattern' validator, which has been changed to
47
- * matche partial values by default (the standard 'pattern' validator wrapped
48
- * all patterns in '^' and '$', forcing them to always match an entire value).
49
- * However, the old behavior can be restored by simply adding '^' and '$'
50
- * around your patterns, or by passing an optional second parameter of TRUE.
51
- * This change is to make the 'pattern' validator match the behavior of a
52
- * JSON Schema pattern, which allows partial matches, rather than the behavior
53
- * of an HTML input control pattern, which does not.
54
- *
55
- * This library replaces Angular's validators and combination functions
56
- * with the following validators and transformation functions:
57
- *
58
- * Validators:
59
- * For all formControls: required (*), type, enum, const
60
- * For text formControls: minLength (*), maxLength (*), pattern (*), format
61
- * For numeric formControls: maximum, exclusiveMaximum,
62
- * minimum, exclusiveMinimum, multipleOf
63
- * For formGroup objects: minProperties, maxProperties, dependencies
64
- * For formArray arrays: minItems, maxItems, uniqueItems, contains
65
- * Not used by JSON Schema: min (*), max (*), requiredTrue (*), email (*)
66
- * (Validators originally included with Angular are maked with (*).)
67
- *
68
- * NOTE / TODO: The dependencies validator is not complete.
69
- * NOTE / TODO: The contains validator is not complete.
70
- *
71
- * Validators not used by JSON Schema (but included for compatibility)
72
- * and their JSON Schema equivalents:
73
- *
74
- * Angular validator | JSON Schema equivalent
75
- * ------------------|-----------------------
76
- * min(number) | minimum(number)
77
- * max(number) | maximum(number)
78
- * requiredTrue() | const(true)
79
- * email() | format('email')
80
- *
81
- * Validator transformation functions:
82
- * composeAnyOf, composeOneOf, composeAllOf, composeNot
83
- * (Angular's original combination funciton, 'compose', is also included for
84
- * backward compatibility, though it is functionally equivalent to composeAllOf,
85
- * asside from its more generic error message.)
86
- *
87
- * All validators have also been extended to accept an optional second argument
88
- * which, if passed a TRUE value, causes the validator to perform the opposite
89
- * of its original finction. (This is used internally to enable 'not' and
90
- * 'composeOneOf' to function and return useful error messages.)
91
- *
92
- * The 'required' validator has also been overloaded so that if called with
93
- * a boolean parameter (or no parameters) it returns the original validator
94
- * function (rather than executing it). However, if it is called with an
95
- * AbstractControl parameter (as was previously required), it behaves
96
- * exactly as before.
97
- *
98
- * This enables all validators (including 'required') to be constructed in
99
- * exactly the same way, so they can be automatically applied using the
100
- * equivalent key names and values taken directly from a JSON Schema.
101
- *
102
- * This source code is partially derived from Angular,
103
- * which is Copyright (c) 2014-2017 Google, Inc.
104
- * Use of this source code is therefore governed by the same MIT-style license
105
- * that can be found in the LICENSE file at https://angular.io/license
106
- *
107
- * Original Angular Validators:
108
- * https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts
109
- */
110
- export class JsonValidators {
111
-
112
- /**
113
- * Validator functions:
114
- *
115
- * For all formControls: required, type, enum, const
116
- * For text formControls: minLength, maxLength, pattern, format
117
- * For numeric formControls: maximum, exclusiveMaximum,
118
- * minimum, exclusiveMinimum, multipleOf
119
- * For formGroup objects: minProperties, maxProperties, dependencies
120
- * For formArray arrays: minItems, maxItems, uniqueItems, contains
121
- *
122
- * TODO: finish dependencies validator
123
- */
124
-
125
- /**
126
- * 'required' validator
127
- *
128
- * This validator is overloaded, compared to the default required validator.
129
- * If called with no parameters, or TRUE, this validator returns the
130
- * 'required' validator function (rather than executing it). This matches
131
- * the behavior of all other validators in this library.
132
- *
133
- * If this validator is called with an AbstractControl parameter
134
- * (as was previously required) it behaves the same as Angular's default
135
- * required validator, and returns an error if the control is empty.
136
- *
137
- * Old behavior: (if input type = AbstractControl)
138
- * // {AbstractControl} control - required control
139
- * // {{[key: string]: boolean}} - returns error message if no input
140
- *
141
- * New behavior: (if no input, or input type = boolean)
142
- * // {boolean = true} required? - true to validate, false to disable
143
- * // {IValidatorFn} - returns the 'required' validator function itself
144
- */
145
- static required(input: AbstractControl): ValidationErrors|null;
146
- static required(input?: boolean): IValidatorFn;
147
-
148
- static required(input?: AbstractControl|boolean): ValidationErrors|null|IValidatorFn {
149
- if (input === undefined) { input = true; }
150
- switch (input) {
151
- case true: // Return required function (do not execute it yet)
152
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
153
- if (invert) { return null; } // if not required, always return valid
154
- return hasValue(control.value) ? null : { 'required': true };
155
- };
156
- case false: // Do nothing (if field is not required, it is always valid)
157
- return JsonValidators.nullValidator;
158
- default: // Execute required function
159
- return hasValue((<AbstractControl>input).value) ? null : { 'required': true };
160
- }
161
- }
162
-
163
- /**
164
- * 'type' validator
165
- *
166
- * Requires a control to only accept values of a specified type,
167
- * or one of an array of types.
168
- *
169
- * Note: SchemaPrimitiveType = 'string'|'number'|'integer'|'boolean'|'null'
170
- *
171
- * // {SchemaPrimitiveType|SchemaPrimitiveType[]} type - type(s) to accept
172
- * // {IValidatorFn}
173
- */
174
- static type(requiredType: SchemaPrimitiveType|SchemaPrimitiveType[]): IValidatorFn {
175
- if (!hasValue(requiredType)) { return JsonValidators.nullValidator; }
176
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
177
- if (isEmpty(control.value)) { return null; }
178
- const currentValue: any = control.value;
179
- const isValid = isArray(requiredType) ?
180
- (<SchemaPrimitiveType[]>requiredType).some(type => isType(currentValue, type)) :
181
- isType(currentValue, <SchemaPrimitiveType>requiredType);
182
- return xor(isValid, invert) ?
183
- null : { 'type': { requiredType, currentValue } };
184
- };
185
- }
186
-
187
- /**
188
- * 'enum' validator
189
- *
190
- * Requires a control to have a value from an enumerated list of values.
191
- *
192
- * Converts types as needed to allow string inputs to still correctly
193
- * match number, boolean, and null enum values.
194
- *
195
- * // {any[]} allowedValues - array of acceptable values
196
- * // {IValidatorFn}
197
- */
198
- static enum(allowedValues: any[]): IValidatorFn {
199
- if (!isArray(allowedValues)) { return JsonValidators.nullValidator; }
200
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
201
- if (isEmpty(control.value)) { return null; }
202
- const currentValue: any = control.value;
203
- const isEqualVal = (enumValue, inputValue) =>
204
- enumValue === inputValue ||
205
- (isNumber(enumValue) && +inputValue === +enumValue) ||
206
- (isBoolean(enumValue, 'strict') &&
207
- toJavaScriptType(inputValue, 'boolean') === enumValue) ||
208
- (enumValue === null && !hasValue(inputValue)) ||
209
- isEqual(enumValue, inputValue);
210
- const isValid = isArray(currentValue) ?
211
- currentValue.every(inputValue => allowedValues.some(enumValue =>
212
- isEqualVal(enumValue, inputValue)
213
- )) :
214
- allowedValues.some(enumValue => isEqualVal(enumValue, currentValue));
215
- return xor(isValid, invert) ?
216
- null : { 'enum': { allowedValues, currentValue } };
217
- };
218
- }
219
-
220
- /**
221
- * 'const' validator
222
- *
223
- * Requires a control to have a specific value.
224
- *
225
- * Converts types as needed to allow string inputs to still correctly
226
- * match number, boolean, and null values.
227
- *
228
- * TODO: modify to work with objects
229
- *
230
- * // {any[]} requiredValue - required value
231
- * // {IValidatorFn}
232
- */
233
- static const(requiredValue: any): IValidatorFn {
234
- if (!hasValue(requiredValue)) { return JsonValidators.nullValidator; }
235
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
236
- if (isEmpty(control.value)) { return null; }
237
- const currentValue: any = control.value;
238
- const isEqualVal = (constValue, inputValue) =>
239
- constValue === inputValue ||
240
- isNumber(constValue) && +inputValue === +constValue ||
241
- isBoolean(constValue, 'strict') &&
242
- toJavaScriptType(inputValue, 'boolean') === constValue ||
243
- constValue === null && !hasValue(inputValue);
244
- const isValid = isEqualVal(requiredValue, currentValue);
245
- return xor(isValid, invert) ?
246
- null : { 'const': { requiredValue, currentValue } };
247
- };
248
- }
249
-
250
- /**
251
- * 'minLength' validator
252
- *
253
- * Requires a control's text value to be greater than a specified length.
254
- *
255
- * // {number} minimumLength - minimum allowed string length
256
- * // {boolean = false} invert - instead return error object only if valid
257
- * // {IValidatorFn}
258
- */
259
- static minLength(minimumLength: number): IValidatorFn {
260
- if (!hasValue(minimumLength)) { return JsonValidators.nullValidator; }
261
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
262
- if (isEmpty(control.value)) { return null; }
263
- const currentLength = isString(control.value) ? control.value.length : 0;
264
- const isValid = currentLength >= minimumLength;
265
- return xor(isValid, invert) ?
266
- null : { 'minLength': { minimumLength, currentLength } };
267
- };
268
- }
269
-
270
- /**
271
- * 'maxLength' validator
272
- *
273
- * Requires a control's text value to be less than a specified length.
274
- *
275
- * // {number} maximumLength - maximum allowed string length
276
- * // {boolean = false} invert - instead return error object only if valid
277
- * // {IValidatorFn}
278
- */
279
- static maxLength(maximumLength: number): IValidatorFn {
280
- if (!hasValue(maximumLength)) { return JsonValidators.nullValidator; }
281
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
282
- const currentLength = isString(control.value) ? control.value.length : 0;
283
- const isValid = currentLength <= maximumLength;
284
- return xor(isValid, invert) ?
285
- null : { 'maxLength': { maximumLength, currentLength } };
286
- };
287
- }
288
-
289
- /**
290
- * 'pattern' validator
291
- *
292
- * Note: NOT the same as Angular's default pattern validator.
293
- *
294
- * Requires a control's value to match a specified regular expression pattern.
295
- *
296
- * This validator changes the behavior of default pattern validator
297
- * by replacing RegExp(`^${pattern}$`) with RegExp(`${pattern}`),
298
- * which allows for partial matches.
299
- *
300
- * To return to the default funcitonality, and match the entire string,
301
- * pass TRUE as the optional second parameter.
302
- *
303
- * // {string} pattern - regular expression pattern
304
- * // {boolean = false} wholeString - match whole value string?
305
- * // {IValidatorFn}
306
- */
307
- static pattern(pattern: string|RegExp, wholeString = false): IValidatorFn {
308
- if (!hasValue(pattern)) { return JsonValidators.nullValidator; }
309
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
310
- if (isEmpty(control.value)) { return null; }
311
- let regex: RegExp;
312
- let requiredPattern: string;
313
- if (typeof pattern === 'string') {
314
- requiredPattern = (wholeString) ? `^${pattern}$` : pattern;
315
- regex = new RegExp(requiredPattern);
316
- } else {
317
- requiredPattern = pattern.toString();
318
- regex = pattern;
319
- }
320
- const currentValue: string = control.value;
321
- const isValid = isString(currentValue) ? regex.test(currentValue) : false;
322
- return xor(isValid, invert) ?
323
- null : { 'pattern': { requiredPattern, currentValue } };
324
- };
325
- }
326
-
327
- /**
328
- * 'format' validator
329
- *
330
- * Requires a control to have a value of a certain format.
331
- *
332
- * This validator currently checks the following formsts:
333
- * date, time, date-time, email, hostname, ipv4, ipv6,
334
- * uri, uri-reference, uri-template, url, uuid, color,
335
- * json-pointer, relative-json-pointer, regex
336
- *
337
- * Fast format regular expressions copied from AJV:
338
- * https://github.com/epoberezkin/ajv/blob/master/lib/compile/formats.js
339
- *
340
- * // {JsonSchemaFormatNames} requiredFormat - format to check
341
- * // {IValidatorFn}
342
- */
343
- static format(requiredFormat: JsonSchemaFormatNames): IValidatorFn {
344
- if (!hasValue(requiredFormat)) { return JsonValidators.nullValidator; }
345
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
346
- if (isEmpty(control.value)) { return null; }
347
- let isValid: boolean;
348
- const currentValue: string|Date = control.value;
349
- if (isString(currentValue)) {
350
- const formatTest: Function|RegExp = jsonSchemaFormatTests[requiredFormat];
351
- if (typeof formatTest === 'object') {
352
- isValid = (<RegExp>formatTest).test(<string>currentValue);
353
- } else if (typeof formatTest === 'function') {
354
- isValid = (<Function>formatTest)(<string>currentValue);
355
- } else {
356
- console.error(`format validator error: "${requiredFormat}" is not a recognized format.`);
357
- isValid = true;
358
- }
359
- } else {
360
- // Allow JavaScript Date objects
361
- isValid = ['date', 'time', 'date-time'].includes(requiredFormat) &&
362
- Object.prototype.toString.call(currentValue) === '[object Date]';
363
- }
364
- return xor(isValid, invert) ?
365
- null : { 'format': { requiredFormat, currentValue } };
366
- };
367
- }
368
-
369
- /**
370
- * 'minimum' validator
371
- *
372
- * Requires a control's numeric value to be greater than or equal to
373
- * a minimum amount.
374
- *
375
- * Any non-numeric value is also valid (according to the HTML forms spec,
376
- * a non-numeric value doesn't have a minimum).
377
- * https://www.w3.org/TR/html5/forms.html#attr-input-max
378
- *
379
- * // {number} minimum - minimum allowed value
380
- * // {IValidatorFn}
381
- */
382
- static minimum(minimumValue: number): IValidatorFn {
383
- if (!hasValue(minimumValue)) { return JsonValidators.nullValidator; }
384
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
385
- if (isEmpty(control.value)) { return null; }
386
- const currentValue = control.value;
387
- const isValid = !isNumber(currentValue) || currentValue >= minimumValue;
388
- return xor(isValid, invert) ?
389
- null : { 'minimum': { minimumValue, currentValue } };
390
- };
391
- }
392
-
393
- /**
394
- * 'exclusiveMinimum' validator
395
- *
396
- * Requires a control's numeric value to be less than a maximum amount.
397
- *
398
- * Any non-numeric value is also valid (according to the HTML forms spec,
399
- * a non-numeric value doesn't have a maximum).
400
- * https://www.w3.org/TR/html5/forms.html#attr-input-max
401
- *
402
- * // {number} exclusiveMinimumValue - maximum allowed value
403
- * // {IValidatorFn}
404
- */
405
- static exclusiveMinimum(exclusiveMinimumValue: number): IValidatorFn {
406
- if (!hasValue(exclusiveMinimumValue)) { return JsonValidators.nullValidator; }
407
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
408
- if (isEmpty(control.value)) { return null; }
409
- const currentValue = control.value;
410
- const isValid = !isNumber(currentValue) || +currentValue < exclusiveMinimumValue;
411
- return xor(isValid, invert) ?
412
- null : { 'exclusiveMinimum': { exclusiveMinimumValue, currentValue } };
413
- };
414
- }
415
-
416
- /**
417
- * 'maximum' validator
418
- *
419
- * Requires a control's numeric value to be less than or equal to
420
- * a maximum amount.
421
- *
422
- * Any non-numeric value is also valid (according to the HTML forms spec,
423
- * a non-numeric value doesn't have a maximum).
424
- * https://www.w3.org/TR/html5/forms.html#attr-input-max
425
- *
426
- * // {number} maximumValue - maximum allowed value
427
- * // {IValidatorFn}
428
- */
429
- static maximum(maximumValue: number): IValidatorFn {
430
- if (!hasValue(maximumValue)) { return JsonValidators.nullValidator; }
431
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
432
- if (isEmpty(control.value)) { return null; }
433
- const currentValue = control.value;
434
- const isValid = !isNumber(currentValue) || +currentValue <= maximumValue;
435
- return xor(isValid, invert) ?
436
- null : { 'maximum': { maximumValue, currentValue } };
437
- };
438
- }
439
-
440
- /**
441
- * 'exclusiveMaximum' validator
442
- *
443
- * Requires a control's numeric value to be less than a maximum amount.
444
- *
445
- * Any non-numeric value is also valid (according to the HTML forms spec,
446
- * a non-numeric value doesn't have a maximum).
447
- * https://www.w3.org/TR/html5/forms.html#attr-input-max
448
- *
449
- * // {number} exclusiveMaximumValue - maximum allowed value
450
- * // {IValidatorFn}
451
- */
452
- static exclusiveMaximum(exclusiveMaximumValue: number): IValidatorFn {
453
- if (!hasValue(exclusiveMaximumValue)) { return JsonValidators.nullValidator; }
454
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
455
- if (isEmpty(control.value)) { return null; }
456
- const currentValue = control.value;
457
- const isValid = !isNumber(currentValue) || +currentValue < exclusiveMaximumValue;
458
- return xor(isValid, invert) ?
459
- null : { 'exclusiveMaximum': { exclusiveMaximumValue, currentValue } };
460
- };
461
- }
462
-
463
- /**
464
- * 'multipleOf' validator
465
- *
466
- * Requires a control to have a numeric value that is a multiple
467
- * of a specified number.
468
- *
469
- * // {number} multipleOfValue - number value must be a multiple of
470
- * // {IValidatorFn}
471
- */
472
- static multipleOf(multipleOfValue: number): IValidatorFn {
473
- if (!hasValue(multipleOfValue)) { return JsonValidators.nullValidator; }
474
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
475
- if (isEmpty(control.value)) { return null; }
476
- const currentValue = control.value;
477
- const isValid = isNumber(currentValue) &&
478
- currentValue % multipleOfValue === 0;
479
- return xor(isValid, invert) ?
480
- null : { 'multipleOf': { multipleOfValue, currentValue } };
481
- };
482
- }
483
-
484
- /**
485
- * 'minProperties' validator
486
- *
487
- * Requires a form group to have a minimum number of properties (i.e. have
488
- * values entered in a minimum number of controls within the group).
489
- *
490
- * // {number} minimumProperties - minimum number of properties allowed
491
- * // {IValidatorFn}
492
- */
493
- static minProperties(minimumProperties: number): IValidatorFn {
494
- if (!hasValue(minimumProperties)) { return JsonValidators.nullValidator; }
495
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
496
- if (isEmpty(control.value)) { return null; }
497
- const currentProperties = Object.keys(control.value).length || 0;
498
- const isValid = currentProperties >= minimumProperties;
499
- return xor(isValid, invert) ?
500
- null : { 'minProperties': { minimumProperties, currentProperties } };
501
- };
502
- }
503
-
504
- /**
505
- * 'maxProperties' validator
506
- *
507
- * Requires a form group to have a maximum number of properties (i.e. have
508
- * values entered in a maximum number of controls within the group).
509
- *
510
- * Note: Has no effect if the form group does not contain more than the
511
- * maximum number of controls.
512
- *
513
- * // {number} maximumProperties - maximum number of properties allowed
514
- * // {IValidatorFn}
515
- */
516
- static maxProperties(maximumProperties: number): IValidatorFn {
517
- if (!hasValue(maximumProperties)) { return JsonValidators.nullValidator; }
518
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
519
- const currentProperties = Object.keys(control.value).length || 0;
520
- const isValid = currentProperties <= maximumProperties;
521
- return xor(isValid, invert) ?
522
- null : { 'maxProperties': { maximumProperties, currentProperties } };
523
- };
524
- }
525
-
526
- /**
527
- * 'dependencies' validator
528
- *
529
- * Requires the controls in a form group to meet additional validation
530
- * criteria, depending on the values of other controls in the group.
531
- *
532
- * Examples:
533
- * https://spacetelescope.github.io/understanding-json-schema/reference/object.html#dependencies
534
- *
535
- * // {any} dependencies - required dependencies
536
- * // {IValidatorFn}
537
- */
538
- static dependencies(dependencies: any): IValidatorFn {
539
- if (getType(dependencies) !== 'object' || isEmpty(dependencies)) {
540
- return JsonValidators.nullValidator;
541
- }
542
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
543
- if (isEmpty(control.value)) { return null; }
544
- const allErrors = _mergeObjects(
545
- forEachCopy(dependencies, (value, requiringField) => {
546
- if (!hasValue(control.value[requiringField])) { return null; }
547
- let requiringFieldErrors: ValidationErrors = { };
548
- let requiredFields: string[];
549
- let properties: ValidationErrors = { };
550
- if (getType(dependencies[requiringField]) === 'array') {
551
- requiredFields = dependencies[requiringField];
552
- } else if (getType(dependencies[requiringField]) === 'object') {
553
- requiredFields = dependencies[requiringField]['required'] || [];
554
- properties = dependencies[requiringField]['properties'] || { };
555
- }
556
-
557
- // Validate property dependencies
558
- for (const requiredField of requiredFields) {
559
- if (xor(!hasValue(control.value[requiredField]), invert)) {
560
- requiringFieldErrors[requiredField] = { 'required': true };
561
- }
562
- }
563
-
564
- // Validate schema dependencies
565
- requiringFieldErrors = _mergeObjects(requiringFieldErrors,
566
- forEachCopy(properties, (requirements, requiredField) => {
567
- const requiredFieldErrors = _mergeObjects(
568
- forEachCopy(requirements, (requirement, parameter) => {
569
- let validator: IValidatorFn = null;
570
- if (requirement === 'maximum' || requirement === 'minimum') {
571
- const exclusive = !!requirements['exclusiveM' + requirement.slice(1)];
572
- validator = JsonValidators[requirement](parameter, exclusive);
573
- } else if (typeof JsonValidators[requirement] === 'function') {
574
- validator = JsonValidators[requirement](parameter);
575
- }
576
- return !isDefined(validator) ?
577
- null : validator(control.value[requiredField]);
578
- })
579
- );
580
- return isEmpty(requiredFieldErrors) ?
581
- null : { [requiredField]: requiredFieldErrors };
582
- })
583
- );
584
- return isEmpty(requiringFieldErrors) ?
585
- null : { [requiringField]: requiringFieldErrors };
586
- })
587
- );
588
- return isEmpty(allErrors) ? null : allErrors;
589
- };
590
- }
591
-
592
- /**
593
- * 'minItems' validator
594
- *
595
- * Requires a form array to have a minimum number of values.
596
- *
597
- * // {number} minimumItems - minimum number of items allowed
598
- * // {IValidatorFn}
599
- */
600
- static minItems(minimumItems: number): IValidatorFn {
601
- if (!hasValue(minimumItems)) { return JsonValidators.nullValidator; }
602
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
603
- if (isEmpty(control.value)) { return null; }
604
- const currentItems = isArray(control.value) ? control.value.length : 0;
605
- const isValid = currentItems >= minimumItems;
606
- return xor(isValid, invert) ?
607
- null : { 'minItems': { minimumItems, currentItems } };
608
- };
609
- }
610
-
611
- /**
612
- * 'maxItems' validator
613
- *
614
- * Requires a form array to have a maximum number of values.
615
- *
616
- * // {number} maximumItems - maximum number of items allowed
617
- * // {IValidatorFn}
618
- */
619
- static maxItems(maximumItems: number): IValidatorFn {
620
- if (!hasValue(maximumItems)) { return JsonValidators.nullValidator; }
621
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
622
- const currentItems = isArray(control.value) ? control.value.length : 0;
623
- const isValid = currentItems <= maximumItems;
624
- return xor(isValid, invert) ?
625
- null : { 'maxItems': { maximumItems, currentItems } };
626
- };
627
- }
628
-
629
- /**
630
- * 'uniqueItems' validator
631
- *
632
- * Requires values in a form array to be unique.
633
- *
634
- * // {boolean = true} unique? - true to validate, false to disable
635
- * // {IValidatorFn}
636
- */
637
- static uniqueItems(unique = true): IValidatorFn {
638
- if (!unique) { return JsonValidators.nullValidator; }
639
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
640
- if (isEmpty(control.value)) { return null; }
641
- const sorted: any[] = control.value.slice().sort();
642
- const duplicateItems = [];
643
- for (let i = 1; i < sorted.length; i++) {
644
- if (sorted[i - 1] === sorted[i] && duplicateItems.includes(sorted[i])) {
645
- duplicateItems.push(sorted[i]);
646
- }
647
- }
648
- const isValid = !duplicateItems.length;
649
- return xor(isValid, invert) ?
650
- null : { 'uniqueItems': { duplicateItems } };
651
- };
652
- }
653
-
654
- /**
655
- * 'contains' validator
656
- *
657
- * TODO: Complete this validator
658
- *
659
- * Requires values in a form array to be unique.
660
- *
661
- * // {boolean = true} unique? - true to validate, false to disable
662
- * // {IValidatorFn}
663
- */
664
- static contains(requiredItem = true): IValidatorFn {
665
- if (!requiredItem) { return JsonValidators.nullValidator; }
666
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
667
- if (isEmpty(control.value) || !isArray(control.value)) { return null; }
668
- const currentItems = control.value;
669
- // const isValid = currentItems.some(item =>
670
- //
671
- // );
672
- const isValid = true;
673
- return xor(isValid, invert) ?
674
- null : { 'contains': { requiredItem, currentItems } };
675
- };
676
- }
677
-
678
- /**
679
- * No-op validator. Included for backward compatibility.
680
- */
681
- static nullValidator(control: AbstractControl): ValidationErrors|null {
682
- return null;
683
- }
684
-
685
- /**
686
- * Validator transformation functions:
687
- * composeAnyOf, composeOneOf, composeAllOf, composeNot,
688
- * compose, composeAsync
689
- *
690
- * TODO: Add composeAnyOfAsync, composeOneOfAsync,
691
- * composeAllOfAsync, composeNotAsync
692
- */
693
-
694
- /**
695
- * 'composeAnyOf' validator combination function
696
- *
697
- * Accepts an array of validators and returns a single validator that
698
- * evaluates to valid if any one or more of the submitted validators are
699
- * valid. If every validator is invalid, it returns combined errors from
700
- * all validators.
701
- *
702
- * // {IValidatorFn[]} validators - array of validators to combine
703
- * // {IValidatorFn} - single combined validator function
704
- */
705
- static composeAnyOf(validators: IValidatorFn[]): IValidatorFn {
706
- if (!validators) { return null; }
707
- const presentValidators = validators.filter(isDefined);
708
- if (presentValidators.length === 0) { return null; }
709
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
710
- const arrayOfErrors =
711
- _executeValidators(control, presentValidators, invert).filter(isDefined);
712
- const isValid = validators.length > arrayOfErrors.length;
713
- return xor(isValid, invert) ?
714
- null : _mergeObjects(...arrayOfErrors, { 'anyOf': !invert });
715
- };
716
- }
717
-
718
- /**
719
- * 'composeOneOf' validator combination function
720
- *
721
- * Accepts an array of validators and returns a single validator that
722
- * evaluates to valid only if exactly one of the submitted validators
723
- * is valid. Otherwise returns combined information from all validators,
724
- * both valid and invalid.
725
- *
726
- * // {IValidatorFn[]} validators - array of validators to combine
727
- * // {IValidatorFn} - single combined validator function
728
- */
729
- static composeOneOf(validators: IValidatorFn[]): IValidatorFn {
730
- if (!validators) { return null; }
731
- const presentValidators = validators.filter(isDefined);
732
- if (presentValidators.length === 0) { return null; }
733
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
734
- const arrayOfErrors =
735
- _executeValidators(control, presentValidators);
736
- const validControls =
737
- validators.length - arrayOfErrors.filter(isDefined).length;
738
- const isValid = validControls === 1;
739
- if (xor(isValid, invert)) { return null; }
740
- const arrayOfValids =
741
- _executeValidators(control, presentValidators, invert);
742
- return _mergeObjects(...arrayOfErrors, ...arrayOfValids, { 'oneOf': !invert });
743
- };
744
- }
745
-
746
- /**
747
- * 'composeAllOf' validator combination function
748
- *
749
- * Accepts an array of validators and returns a single validator that
750
- * evaluates to valid only if all the submitted validators are individually
751
- * valid. Otherwise it returns combined errors from all invalid validators.
752
- *
753
- * // {IValidatorFn[]} validators - array of validators to combine
754
- * // {IValidatorFn} - single combined validator function
755
- */
756
- static composeAllOf(validators: IValidatorFn[]): IValidatorFn {
757
- if (!validators) { return null; }
758
- const presentValidators = validators.filter(isDefined);
759
- if (presentValidators.length === 0) { return null; }
760
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
761
- const combinedErrors = _mergeErrors(
762
- _executeValidators(control, presentValidators, invert)
763
- );
764
- const isValid = combinedErrors === null;
765
- return (xor(isValid, invert)) ?
766
- null : _mergeObjects(combinedErrors, { 'allOf': !invert });
767
- };
768
- }
769
-
770
- /**
771
- * 'composeNot' validator inversion function
772
- *
773
- * Accepts a single validator function and inverts its result.
774
- * Returns valid if the submitted validator is invalid, and
775
- * returns invalid if the submitted validator is valid.
776
- * (Note: this function can itself be inverted
777
- * - e.g. composeNot(composeNot(validator)) -
778
- * but this can be confusing and is therefore not recommended.)
779
- *
780
- * // {IValidatorFn[]} validators - validator(s) to invert
781
- * // {IValidatorFn} - new validator function that returns opposite result
782
- */
783
- static composeNot(validator: IValidatorFn): IValidatorFn {
784
- if (!validator) { return null; }
785
- return (control: AbstractControl, invert = false): ValidationErrors|null => {
786
- if (isEmpty(control.value)) { return null; }
787
- const error = validator(control, !invert);
788
- const isValid = error === null;
789
- return (xor(isValid, invert)) ?
790
- null : _mergeObjects(error, { 'not': !invert });
791
- };
792
- }
793
-
794
- /**
795
- * 'compose' validator combination function
796
- *
797
- * // {IValidatorFn[]} validators - array of validators to combine
798
- * // {IValidatorFn} - single combined validator function
799
- */
800
- static compose(validators: IValidatorFn[]): IValidatorFn {
801
- if (!validators) { return null; }
802
- const presentValidators = validators.filter(isDefined);
803
- if (presentValidators.length === 0) { return null; }
804
- return (control: AbstractControl, invert = false): ValidationErrors|null =>
805
- _mergeErrors(_executeValidators(control, presentValidators, invert));
806
- }
807
-
808
- /**
809
- * 'composeAsync' async validator combination function
810
- *
811
- * // {AsyncIValidatorFn[]} async validators - array of async validators
812
- * // {AsyncIValidatorFn} - single combined async validator function
813
- */
814
- static composeAsync(validators: AsyncIValidatorFn[]): AsyncIValidatorFn {
815
- if (!validators) { return null; }
816
- const presentValidators = validators.filter(isDefined);
817
- if (presentValidators.length === 0) { return null; }
818
- return (control: AbstractControl) => {
819
- const observables =
820
- _executeAsyncValidators(control, presentValidators).map(toObservable);
821
- return map.call(forkJoin(observables), _mergeErrors);
822
- };
823
- }
824
-
825
- // Additional angular validators (not used by Angualr JSON Schema Form)
826
- // From https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts
827
-
828
- /**
829
- * Validator that requires controls to have a value greater than a number.
830
- */
831
- static min(min: number): ValidatorFn {
832
- if (!hasValue(min)) { return JsonValidators.nullValidator; }
833
- return (control: AbstractControl): ValidationErrors|null => {
834
- // don't validate empty values to allow optional controls
835
- if (isEmpty(control.value) || isEmpty(min)) { return null; }
836
- const value = parseFloat(control.value);
837
- const actual = control.value;
838
- // Controls with NaN values after parsing should be treated as not having a
839
- // minimum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-min
840
- return isNaN(value) || value >= min ? null : { 'min': { min, actual } };
841
- };
842
- }
843
-
844
- /**
845
- * Validator that requires controls to have a value less than a number.
846
- */
847
- static max(max: number): ValidatorFn {
848
- if (!hasValue(max)) { return JsonValidators.nullValidator; }
849
- return (control: AbstractControl): ValidationErrors|null => {
850
- // don't validate empty values to allow optional controls
851
- if (isEmpty(control.value) || isEmpty(max)) { return null; }
852
- const value = parseFloat(control.value);
853
- const actual = control.value;
854
- // Controls with NaN values after parsing should be treated as not having a
855
- // maximum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-max
856
- return isNaN(value) || value <= max ? null : { 'max': { max, actual } };
857
- };
858
- }
859
-
860
- /**
861
- * Validator that requires control value to be true.
862
- */
863
- static requiredTrue(control: AbstractControl): ValidationErrors|null {
864
- if (!control) { return JsonValidators.nullValidator; }
865
- return control.value === true ? null : { 'required': true };
866
- }
867
-
868
- /**
869
- * Validator that performs email validation.
870
- */
871
- static email(control: AbstractControl): ValidationErrors|null {
872
- if (!control) { return JsonValidators.nullValidator; }
873
- const EMAIL_REGEXP =
874
- // tslint:disable-next-line:max-line-length
875
- /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/;
876
- return EMAIL_REGEXP.test(control.value) ? null : { 'email': true };
877
- }
878
- }