@fagon/ngx-intellitoolx 16.0.2 → 16.0.4
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.
- package/README.md +664 -465
- package/esm2022/lib/form-errors/form-errors.component.mjs +3 -3
- package/esm2022/lib/form-validators/max-words.validator.mjs +2 -2
- package/esm2022/lib/form-validators/password-mismatch.validator.mjs +2 -2
- package/fesm2022/fagon-ngx-intellitoolx.mjs +5 -5
- package/fesm2022/fagon-ngx-intellitoolx.mjs.map +1 -1
- package/lib/form-errors/form-errors.component.d.ts +1 -1
- package/lib/form-validators/max-words.validator.d.ts +2 -2
- package/lib/form-validators/password-mismatch.validator.d.ts +1 -1
- package/package.json +16 -2
package/README.md
CHANGED
|
@@ -1,303 +1,386 @@
|
|
|
1
|
+
# IntelliToolx
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
IntelliToolx is a comprehensive Angular utility library designed to simplify reactive form development, validation, and user experience.
|
|
12
|
+
|
|
13
|
+
It provides powerful helpers, reusable validators, smart error handling, UI components, and developer-friendly utilities that eliminate repetitive boilerplate and enforce consistent form behavior across applications.
|
|
14
|
+
|
|
15
|
+
Built with scalability, accessibility, and maintainability in mind, IntelliToolx helps teams build robust, user-friendly form workflows faster and with fewer bugs.
|
|
16
|
+
|
|
17
|
+
### Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install intellitoolx
|
|
21
|
+
```
|
|
22
|
+
|
|
1
23
|
# IntelliToolxHelper
|
|
2
24
|
|
|
3
25
|
Utility helpers for working with Angular Reactive Forms, deep comparisons, change detection, and common data transformations.
|
|
4
26
|
Designed to simplify form state management, prevent accidental navigation, and normalize user input.
|
|
5
27
|
|
|
6
|
-
|
|
28
|
+
### Import
|
|
7
29
|
|
|
8
|
-
|
|
30
|
+
```ts
|
|
31
|
+
import { IntelliToolxHelper } from "intellitoolx";
|
|
32
|
+
```
|
|
9
33
|
|
|
10
|
-
Methods
|
|
34
|
+
## Methods
|
|
11
35
|
|
|
12
|
-
|
|
36
|
+
### captureInitialFormValue(form)
|
|
13
37
|
|
|
14
38
|
Captures and clones the initial value of a form and marks it as pristine.
|
|
15
39
|
|
|
16
|
-
|
|
40
|
+
```ts
|
|
41
|
+
static captureInitialFormValue(form: AbstractControl): any
|
|
42
|
+
```
|
|
17
43
|
|
|
18
44
|
Features
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
45
|
+
|
|
46
|
+
- Uses getRawValue() when available
|
|
47
|
+
- Marks form as pristine
|
|
48
|
+
- Returns a deep clone of the initial value
|
|
22
49
|
|
|
23
50
|
Example
|
|
24
|
-
const initial = IntelliToolxHelper.captureInitialValue(this.form);
|
|
25
51
|
|
|
26
|
-
|
|
52
|
+
```ts
|
|
53
|
+
const initial = IntelliToolxHelper.captureInitialFormValue(this.form);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### trimFormGroup(control)
|
|
27
57
|
|
|
28
58
|
Recursively trims whitespace from all string values in a form.
|
|
29
59
|
|
|
60
|
+
```ts
|
|
30
61
|
static trimFormGroup(control: AbstractControl): void
|
|
62
|
+
```
|
|
31
63
|
|
|
32
64
|
Supports
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
65
|
+
|
|
66
|
+
- FormGroup
|
|
67
|
+
- FormArray
|
|
68
|
+
- FormControl
|
|
36
69
|
|
|
37
70
|
Example
|
|
71
|
+
|
|
72
|
+
```ts
|
|
38
73
|
IntelliToolxHelper.trimFormGroup(this.form);
|
|
74
|
+
```
|
|
39
75
|
|
|
40
|
-
|
|
76
|
+
### deepEqual(obj1, obj2)
|
|
41
77
|
|
|
42
78
|
Performs a deep comparison between two values.
|
|
43
79
|
|
|
80
|
+
```ts
|
|
44
81
|
static deepEqual(obj1: any, obj2: any): boolean
|
|
82
|
+
```
|
|
45
83
|
|
|
46
84
|
Special behavior
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
85
|
+
|
|
86
|
+
- Treats null, undefined, and "" as equal
|
|
87
|
+
- Normalizes numeric comparisons
|
|
88
|
+
- Compares File objects by metadata
|
|
89
|
+
- Supports nested objects & arrays
|
|
51
90
|
|
|
52
91
|
Example
|
|
92
|
+
|
|
93
|
+
```ts
|
|
53
94
|
IntelliToolxHelper.deepEqual(a, b);
|
|
95
|
+
```
|
|
54
96
|
|
|
55
|
-
|
|
97
|
+
### isEmpty(value)
|
|
56
98
|
|
|
57
99
|
Checks if a value is empty.
|
|
58
100
|
|
|
101
|
+
```ts
|
|
59
102
|
static isEmpty(value: any): boolean
|
|
103
|
+
```
|
|
60
104
|
|
|
61
|
-
Returns true for:
|
|
62
|
-
null
|
|
63
|
-
undefined
|
|
64
|
-
empty string
|
|
65
|
-
whitespace-only string
|
|
105
|
+
Returns true for: `null, undefined, empty string, whitespace-only string `
|
|
66
106
|
|
|
67
|
-
|
|
107
|
+
### clone(value)
|
|
68
108
|
|
|
69
109
|
Creates a deep clone.
|
|
70
110
|
|
|
111
|
+
```ts
|
|
71
112
|
static clone(value: any): any
|
|
113
|
+
```
|
|
72
114
|
|
|
73
115
|
Uses structuredClone (Angular 14+ compatible).
|
|
74
116
|
|
|
75
|
-
|
|
117
|
+
### formHasChanges(initialValue, form)
|
|
76
118
|
|
|
77
119
|
Determines whether a form value has changed.
|
|
78
120
|
|
|
121
|
+
```ts
|
|
79
122
|
static formHasChanges(initialValue: any, form: AbstractControl): boolean
|
|
123
|
+
```
|
|
80
124
|
|
|
81
125
|
Example
|
|
126
|
+
|
|
127
|
+
```ts
|
|
82
128
|
if (IntelliToolxHelper.formHasChanges(initial, this.form)) {
|
|
83
|
-
// prompt user
|
|
129
|
+
// prompt user
|
|
84
130
|
}
|
|
131
|
+
```
|
|
85
132
|
|
|
86
|
-
|
|
133
|
+
### confirmIfChanged(hasChanges, confirmHandler?)
|
|
87
134
|
|
|
88
135
|
Shows confirmation if changes exist.
|
|
89
136
|
|
|
90
|
-
|
|
91
|
-
hasChanges: boolean,
|
|
92
|
-
|
|
93
|
-
): Promise<boolean>
|
|
137
|
+
```ts
|
|
138
|
+
static confirmIfChanged(hasChanges: boolean, confirmHandler?: ConfirmHandler): Promise<boolean>
|
|
139
|
+
```
|
|
94
140
|
|
|
95
141
|
Behavior
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
142
|
+
|
|
143
|
+
- Returns true if no changes
|
|
144
|
+
- Uses provided handler if available
|
|
145
|
+
- Falls back to browser confirm()
|
|
99
146
|
|
|
100
147
|
Example
|
|
101
|
-
const canLeave = await IntelliToolxHelper.confirmIfChanged(
|
|
102
|
-
hasChanges,
|
|
103
|
-
() => dialog.confirm()
|
|
104
|
-
);
|
|
105
148
|
|
|
106
|
-
|
|
149
|
+
```ts
|
|
150
|
+
const canLeave = await IntelliToolxHelper.confirmIfChanged(hasChanges, () => dialog.confirm());
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### registerBeforeUnload(shouldBlock, message?)
|
|
107
154
|
|
|
108
155
|
Prevents accidental page exit when changes exist.
|
|
109
156
|
|
|
110
|
-
|
|
111
|
-
shouldBlock: () => boolean,
|
|
112
|
-
|
|
113
|
-
): () => void
|
|
157
|
+
```ts
|
|
158
|
+
static registerBeforeUnload(shouldBlock: () => boolean, message?: string): () => void
|
|
159
|
+
```
|
|
114
160
|
|
|
115
|
-
Returns
|
|
116
|
-
Cleanup function to remove the listener.
|
|
161
|
+
Returns `Cleanup function to remove the listener.`
|
|
117
162
|
|
|
118
163
|
Example
|
|
119
|
-
const cleanup = IntelliToolxHelper.registerBeforeUnload(() =>
|
|
120
|
-
this.form.dirty
|
|
121
|
-
);
|
|
122
164
|
|
|
165
|
+
```ts
|
|
166
|
+
const cleanup = IntelliToolxHelper.registerBeforeUnload(() => this.form.dirty);
|
|
123
167
|
// later
|
|
124
168
|
cleanup();
|
|
169
|
+
```
|
|
125
170
|
|
|
126
|
-
|
|
171
|
+
### getFormControl(form, path)
|
|
127
172
|
|
|
128
173
|
Retrieves a nested FormControl using dot notation.
|
|
129
174
|
|
|
130
|
-
|
|
131
|
-
form: AbstractControl,
|
|
132
|
-
|
|
133
|
-
): FormControl<T> | null
|
|
175
|
+
```ts
|
|
176
|
+
static getFormControl<T>(form: AbstractControl, path: string): FormControl<T> | null
|
|
177
|
+
```
|
|
134
178
|
|
|
135
179
|
Supports
|
|
136
|
-
|
|
137
|
-
|
|
180
|
+
|
|
181
|
+
- Nested FormGroups
|
|
182
|
+
- FormArrays using numeric indexes
|
|
138
183
|
|
|
139
184
|
Example
|
|
140
|
-
const control = IntelliToolxHelper.getFormControl(this.form, 'address.street');
|
|
141
|
-
const item = IntelliToolxHelper.getFormControl(this.form, 'items.0.name');
|
|
142
185
|
|
|
143
|
-
|
|
186
|
+
```ts
|
|
187
|
+
const control = IntelliToolxHelper.getFormControl(this.form, "address.street");
|
|
188
|
+
const item = IntelliToolxHelper.getFormControl(this.form, "items.0.name");
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### convertImageToBase64(file)
|
|
144
192
|
|
|
145
193
|
Converts an image file to a Base64 string.
|
|
146
194
|
|
|
195
|
+
```ts
|
|
147
196
|
static convertImageToBase64(file: File): Promise<string>
|
|
197
|
+
```
|
|
148
198
|
|
|
149
199
|
Example
|
|
200
|
+
|
|
201
|
+
```ts
|
|
150
202
|
const base64 = await IntelliToolxHelper.convertImageToBase64(file);
|
|
203
|
+
```
|
|
151
204
|
|
|
152
|
-
|
|
205
|
+
### replaceCharacter(text, replaceChar, replaceWithChar)
|
|
153
206
|
|
|
154
207
|
Replaces all occurrences of a character in a string.
|
|
155
208
|
|
|
156
|
-
|
|
157
|
-
text: any,
|
|
158
|
-
|
|
159
|
-
replaceWithChar: string
|
|
160
|
-
): string
|
|
209
|
+
```ts
|
|
210
|
+
static replaceCharacter(text: any, replaceChar: string, replaceWithChar: string): string
|
|
211
|
+
```
|
|
161
212
|
|
|
162
213
|
Example
|
|
163
|
-
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
IntelliToolxHelper.replaceCharacter("1-2-3", "-", ":");
|
|
164
217
|
// 1:2:3
|
|
218
|
+
```
|
|
165
219
|
|
|
166
|
-
|
|
220
|
+
### convertJsonStringToJson(value)
|
|
167
221
|
|
|
168
222
|
Safely converts a JSON string into an object.
|
|
169
223
|
|
|
170
|
-
|
|
171
|
-
value: T | string | null | undefined
|
|
172
|
-
|
|
224
|
+
```ts
|
|
225
|
+
static convertJsonStringToJson<T>(value: T | string | null | undefined): T | null
|
|
226
|
+
```
|
|
173
227
|
|
|
174
228
|
Behavior
|
|
175
|
-
|
|
176
|
-
Returns
|
|
177
|
-
Returns
|
|
229
|
+
|
|
230
|
+
- Returns parsed object if valid JSON string
|
|
231
|
+
- Returns original object if already parsed
|
|
232
|
+
- Returns null if parsing fails
|
|
178
233
|
|
|
179
234
|
Example
|
|
235
|
+
|
|
236
|
+
```ts
|
|
180
237
|
const data = IntelliToolxHelper.convertJsonStringToJson<MyType>(jsonString);
|
|
238
|
+
```
|
|
181
239
|
|
|
182
|
-
|
|
240
|
+
Usage Pattern (Recommended)
|
|
183
241
|
|
|
184
|
-
|
|
242
|
+
```ts
|
|
243
|
+
initialValue = IntelliToolxHelper.captureInitialFormValue(this.form);
|
|
185
244
|
|
|
186
245
|
save() {
|
|
187
|
-
IntelliToolxHelper.trimFormGroup(this.form);
|
|
188
|
-
|
|
189
|
-
if (!IntelliToolxHelper.formHasChanges(this.initialValue, this.form)) {
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
246
|
+
IntelliToolxHelper.trimFormGroup(this.form);
|
|
192
247
|
|
|
193
|
-
|
|
248
|
+
if (!IntelliToolxHelper.formHasChanges(this.initialValue, this.form)) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
// proceed with save
|
|
194
252
|
}
|
|
253
|
+
```
|
|
195
254
|
|
|
196
255
|
# IntellitoolxRegExps
|
|
197
256
|
|
|
198
257
|
A collection of commonly used regular expressions for validation in Angular and TypeScript applications.
|
|
199
258
|
|
|
200
|
-
Designed for:
|
|
201
|
-
Reactive Forms validation
|
|
202
|
-
Input sanitization
|
|
203
|
-
Reusable validation patterns
|
|
204
|
-
Consistent form behavior across projects
|
|
259
|
+
1. Designed for:
|
|
260
|
+
2. Reactive Forms validation
|
|
261
|
+
3. Input sanitization
|
|
262
|
+
4. Reusable validation patterns
|
|
263
|
+
5. Consistent form behavior across projects
|
|
205
264
|
|
|
206
|
-
Import
|
|
207
|
-
|
|
265
|
+
### Import
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
import { IntellitoolxRegExps } from "intellitoolx";
|
|
269
|
+
```
|
|
208
270
|
|
|
209
|
-
Available Regular Expressions
|
|
271
|
+
## Available Regular Expressions
|
|
210
272
|
|
|
211
|
-
|
|
273
|
+
### EMAIL_REGEX
|
|
212
274
|
|
|
213
|
-
EMAIL*REGEX: /^(?=.{1,50}$)[a-zA-Z0-9.*%+-]+@[a-zA-Z0-9.-]+\.[A-Za-z]{2,}
|
|
275
|
+
`EMAIL*REGEX: /^(?=.{1,50}$)[a-zA-Z0-9.*%+-]+@[a-zA-Z0-9.-]+\.[A-Za-z]{2,}$/`
|
|
214
276
|
|
|
215
277
|
Validates an email address with:
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
278
|
+
|
|
279
|
+
1. Maximum length of 50 characters
|
|
280
|
+
2. Standard email format
|
|
281
|
+
3. Requires valid domain suffix (min 2 characters)
|
|
219
282
|
|
|
220
283
|
Valid Examples
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
284
|
+
|
|
285
|
+
- test@example.com
|
|
286
|
+
- user.name@mail-domain.org
|
|
287
|
+
- info123@test.co
|
|
224
288
|
|
|
225
289
|
Invalid Examples
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
@
|
|
290
|
+
|
|
291
|
+
- invalid-email
|
|
292
|
+
- user@
|
|
293
|
+
- @test.com
|
|
229
294
|
|
|
230
295
|
Usage (Angular Validator)
|
|
231
296
|
|
|
297
|
+
```ts
|
|
232
298
|
this.form = new FormGroup({
|
|
233
|
-
email: new FormControl(
|
|
234
|
-
Validators.pattern(IntellitoolxRegExps.EMAIL_REGEX),
|
|
235
|
-
]),
|
|
299
|
+
email: new FormControl("", [Validators.pattern(IntellitoolxRegExps.EMAIL_REGEX)]),
|
|
236
300
|
});
|
|
301
|
+
```
|
|
237
302
|
|
|
238
|
-
|
|
303
|
+
### NUMBER_REGEX
|
|
239
304
|
|
|
240
|
-
NUMBER_REGEX: /^\d
|
|
305
|
+
`NUMBER_REGEX: /^\d+$/`
|
|
241
306
|
|
|
242
307
|
Validates:
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
No
|
|
246
|
-
No
|
|
308
|
+
|
|
309
|
+
- Whole numbers only
|
|
310
|
+
- No decimals
|
|
311
|
+
- No negative values
|
|
312
|
+
- No spaces or characters
|
|
247
313
|
|
|
248
314
|
Valid Examples
|
|
249
|
-
|
|
315
|
+
|
|
316
|
+
- 1
|
|
317
|
+
- 25
|
|
318
|
+
- 99999
|
|
250
319
|
|
|
251
320
|
Invalid Examples
|
|
252
|
-
1.5, -10, abc
|
|
253
321
|
|
|
254
|
-
|
|
322
|
+
- 1.5
|
|
323
|
+
- -10
|
|
324
|
+
- abc
|
|
255
325
|
|
|
256
|
-
AMOUNT_REGEX
|
|
326
|
+
### AMOUNT_REGEX
|
|
327
|
+
|
|
328
|
+
`AMOUNT_REGEX: /^\d+(\.\d{1,2})?$/`
|
|
257
329
|
|
|
258
330
|
Validates monetary amounts:
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
331
|
+
|
|
332
|
+
1. Whole numbers
|
|
333
|
+
2. Optional decimal
|
|
334
|
+
3. Maximum 2 decimal places
|
|
262
335
|
|
|
263
336
|
Valid Examples
|
|
264
|
-
|
|
337
|
+
|
|
338
|
+
- 10,
|
|
339
|
+
- 10.5
|
|
340
|
+
- 10.50
|
|
341
|
+
- 9999.99
|
|
265
342
|
|
|
266
343
|
Invalid Examples
|
|
267
|
-
10., 10.999, abc
|
|
268
344
|
|
|
269
|
-
|
|
345
|
+
- 10.
|
|
346
|
+
- 10.999
|
|
347
|
+
- abc
|
|
348
|
+
|
|
349
|
+
### DOMAIN_REGEX
|
|
270
350
|
|
|
271
|
-
DOMAIN_REGEX:
|
|
272
|
-
/^(?=.{1,255}$)(https?|ftp):\/\/([\w.-]+)\.([a-z\.]{2,6})(:[0-9]{1,5})?(\/\S*)?$/
|
|
351
|
+
`DOMAIN_REGEX: /^(?=.{1,255}$)(https?|ftp):\/\/([\w.-]+)\.([a-z\.]{2,6})(:[0-9]{1,5})?(\/\S*)?$/`
|
|
273
352
|
|
|
274
353
|
Validates full URLs with:
|
|
275
354
|
http, https, or ftp protocol
|
|
276
355
|
|
|
277
356
|
Valid domain
|
|
278
|
-
|
|
279
|
-
Optional
|
|
280
|
-
|
|
357
|
+
|
|
358
|
+
1. Optional port
|
|
359
|
+
2. Optional path
|
|
360
|
+
3. Maximum length of 255 characters
|
|
281
361
|
|
|
282
362
|
Valid Examples
|
|
283
|
-
|
|
363
|
+
|
|
364
|
+
- https://example.com
|
|
365
|
+
- http://sub.domain.org
|
|
366
|
+
- https://example.com:8080/path
|
|
367
|
+
- ftp://files.server.net
|
|
284
368
|
|
|
285
369
|
Invalid Examples
|
|
286
|
-
example.com, http:/example.com, htp://domain.com
|
|
287
370
|
|
|
288
|
-
|
|
371
|
+
- example.com
|
|
372
|
+
- http:/example.com
|
|
373
|
+
- htp://domain.com
|
|
289
374
|
|
|
375
|
+
Usage in Angular Reactive Forms
|
|
376
|
+
|
|
377
|
+
```ts
|
|
290
378
|
this.form = new FormGroup({
|
|
291
|
-
email: new FormControl(
|
|
292
|
-
Validators.pattern(IntellitoolxRegExps.
|
|
293
|
-
]),
|
|
294
|
-
amount: new FormControl('', [
|
|
295
|
-
Validators.pattern(IntellitoolxRegExps.AMOUNT_REGEX),
|
|
296
|
-
]),
|
|
297
|
-
website: new FormControl('', [
|
|
298
|
-
Validators.pattern(IntellitoolxRegExps.DOMAIN_REGEX),
|
|
299
|
-
]),
|
|
379
|
+
email: new FormControl("", [Validators.pattern(IntellitoolxRegExps.EMAIL_REGEX)]),
|
|
380
|
+
amount: new FormControl("", [Validators.pattern(IntellitoolxRegExps.AMOUNT_REGEX)]),
|
|
381
|
+
website: new FormControl("", [Validators.pattern(IntellitoolxRegExps.DOMAIN_REGEX)]),
|
|
300
382
|
});
|
|
383
|
+
```
|
|
301
384
|
|
|
302
385
|
# IntellitoolxFormUpdateMessage
|
|
303
386
|
|
|
@@ -305,159 +388,187 @@ A lightweight Angular standalone component that displays a configurable warning
|
|
|
305
388
|
|
|
306
389
|
Designed to improve user experience by clearly informing users why an action (such as saving) cannot proceed.
|
|
307
390
|
|
|
308
|
-
|
|
391
|
+
### Import
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
import { IntellitoolxFormUpdateMessage } from "intellitoolx";
|
|
395
|
+
```
|
|
309
396
|
|
|
310
|
-
import { IntellitoolxFormUpdateMessage } from 'intellitoolx-helper';
|
|
311
397
|
Because it is standalone, import it directly:
|
|
312
398
|
|
|
399
|
+
```ts
|
|
313
400
|
@Component({
|
|
314
|
-
standalone: true,
|
|
315
|
-
imports: [IntellitoolxFormUpdateMessage],
|
|
401
|
+
standalone: true,
|
|
402
|
+
imports: [IntellitoolxFormUpdateMessage],
|
|
316
403
|
})
|
|
404
|
+
```
|
|
317
405
|
|
|
318
|
-
|
|
406
|
+
Basic Usage
|
|
319
407
|
|
|
408
|
+
```
|
|
320
409
|
<itx-form-update-message></itx-form-update-message>
|
|
410
|
+
```
|
|
321
411
|
|
|
322
|
-
|
|
412
|
+
Default message:
|
|
323
413
|
|
|
324
|
-
There are no changes to save. Please modify a field to continue
|
|
325
|
-
|
|
414
|
+
`There are no changes to save. Please modify a field to continue.`
|
|
415
|
+
|
|
416
|
+
### With Configuration
|
|
326
417
|
|
|
327
418
|
Customize text and styling using itxFormUpdateMessageConfig.
|
|
328
419
|
|
|
329
|
-
|
|
330
|
-
[itxFormUpdateMessageConfig]="updateMessageConfig"
|
|
420
|
+
```html
|
|
421
|
+
<itx-form-update-message [itxFormUpdateMessageConfig]="updateMessageConfig"> </itx-form-update-message>
|
|
422
|
+
```
|
|
331
423
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
424
|
+
```ts
|
|
425
|
+
updateMessageConfig = {
|
|
426
|
+
message: "Nothing changed yet.",
|
|
427
|
+
textColor: "#0c5460",
|
|
428
|
+
backgroundColor: "#d1ecf1",
|
|
429
|
+
borderColor: "#bee5eb",
|
|
430
|
+
};
|
|
431
|
+
```
|
|
339
432
|
|
|
340
|
-
|
|
433
|
+
Configuration Interface
|
|
341
434
|
|
|
435
|
+
```ts
|
|
342
436
|
export interface IntellitoolxFormUpdateMessageConfig {
|
|
343
|
-
message?: string;
|
|
344
|
-
textColor?: string;
|
|
345
|
-
backgroundColor?: string;
|
|
346
|
-
borderColor?: string;
|
|
347
|
-
padding?: string;
|
|
348
|
-
iconAndMessageGap?: string;
|
|
349
|
-
borderRadius?: string;
|
|
350
|
-
fontWeight?: number | string;
|
|
351
|
-
iconSize?: string;
|
|
437
|
+
message?: string;
|
|
438
|
+
textColor?: string;
|
|
439
|
+
backgroundColor?: string;
|
|
440
|
+
borderColor?: string;
|
|
441
|
+
padding?: string;
|
|
442
|
+
iconAndMessageGap?: string;
|
|
443
|
+
borderRadius?: string;
|
|
444
|
+
fontWeight?: number | string;
|
|
445
|
+
iconSize?: string;
|
|
352
446
|
}
|
|
447
|
+
```
|
|
353
448
|
|
|
354
449
|
All properties are optional.
|
|
355
450
|
|
|
356
|
-
|
|
357
|
-
|
|
451
|
+
Default Styling Behavior
|
|
358
452
|
If no configuration is provided, the component uses accessible warning styles.
|
|
359
453
|
|
|
360
|
-
Property Default
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
454
|
+
| Property | Default |
|
|
455
|
+
| ------------- | ------- |
|
|
456
|
+
| text color | #963C00 |
|
|
457
|
+
| background | #fff3cd |
|
|
458
|
+
| border | #f3cd5a |
|
|
459
|
+
| padding | 1rem |
|
|
460
|
+
| border radius | 0.5rem |
|
|
461
|
+
| gap | 0.5rem |
|
|
462
|
+
| font weight | 400 |
|
|
463
|
+
| icon size | 1rem |
|
|
464
|
+
|
|
369
465
|
Accessibility
|
|
370
466
|
|
|
371
|
-
Uses role="alert" to notify assistive technologies
|
|
372
|
-
Icon is hidden from screen readers with aria-hidden="true"
|
|
373
|
-
Provides clear visual contrast for warning context
|
|
467
|
+
- Uses role="alert" to notify assistive technologies
|
|
468
|
+
- Icon is hidden from screen readers with aria-hidden="true"
|
|
469
|
+
- Provides clear visual contrast for warning context
|
|
374
470
|
|
|
375
471
|
Example: Show When No Changes Exist
|
|
376
|
-
|
|
377
|
-
|
|
472
|
+
formHasChanges = false;
|
|
473
|
+
|
|
474
|
+
```html
|
|
475
|
+
<itx-form-update-message *ngIf="!formHasChanges"> </itx-form-update-message>
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
Example: Integrating With IntelliToolxHelper
|
|
378
479
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
> hasChanges = IntelliToolxHelper.formHasChanges(this.initialValue, this.form);
|
|
383
|
-
> <itx-form-update-message
|
|
384
|
-
> *ngIf="!hasChanges"
|
|
385
|
-
> </itx-form-update-message>
|
|
480
|
+
```ts
|
|
481
|
+
hasChanges = IntelliToolxHelper.formHasChanges(this.initialValue, this.form);
|
|
482
|
+
```
|
|
386
483
|
|
|
387
|
-
|
|
484
|
+
```html
|
|
485
|
+
<itx-form-update-message *ngIf="!hasChanges"> </itx-form-update-message>
|
|
486
|
+
```
|
|
388
487
|
|
|
488
|
+
Theming Examples
|
|
389
489
|
Success Style
|
|
490
|
+
|
|
491
|
+
```ts
|
|
390
492
|
updateMessageConfig = {
|
|
391
|
-
message:
|
|
392
|
-
textColor:
|
|
393
|
-
backgroundColor:
|
|
394
|
-
borderColor:
|
|
493
|
+
message: "No updates were made.",
|
|
494
|
+
textColor: "#155724",
|
|
495
|
+
backgroundColor: "#d4edda",
|
|
496
|
+
borderColor: "#c3e6cb",
|
|
395
497
|
};
|
|
498
|
+
```
|
|
396
499
|
|
|
397
500
|
Minimal Style
|
|
501
|
+
|
|
502
|
+
```ts
|
|
398
503
|
updateMessageConfig = {
|
|
399
|
-
backgroundColor:
|
|
400
|
-
borderColor:
|
|
401
|
-
textColor:
|
|
504
|
+
backgroundColor: "transparent",
|
|
505
|
+
borderColor: "#ddd",
|
|
506
|
+
textColor: "#555",
|
|
402
507
|
};
|
|
508
|
+
```
|
|
403
509
|
|
|
404
|
-
|
|
405
|
-
|
|
510
|
+
When to Use
|
|
406
511
|
Use this component when:
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
512
|
+
|
|
513
|
+
1. A save/update action is triggered without changes
|
|
514
|
+
2. Preventing redundant submissions
|
|
515
|
+
3. Improving form UX clarity
|
|
516
|
+
4. Displaying inline form state feedback
|
|
411
517
|
|
|
412
518
|
# IntellitoolxFormErrors
|
|
413
519
|
|
|
414
520
|
A lightweight Angular standalone component for displaying reactive form validation errors with customizable and extensible error messages.
|
|
415
|
-
|
|
416
521
|
Built to:
|
|
417
|
-
standardize validation messages
|
|
418
|
-
support component-level overrides
|
|
419
|
-
allow global extension of error messages
|
|
420
|
-
simplify template error handling
|
|
421
522
|
|
|
422
|
-
|
|
423
|
-
|
|
523
|
+
1. standardize validation messages
|
|
524
|
+
2. support component-level overrides
|
|
525
|
+
3. allow global extension of error messages
|
|
526
|
+
4. simplify template error handling
|
|
527
|
+
|
|
528
|
+
### Import
|
|
529
|
+
|
|
530
|
+
```ts
|
|
531
|
+
import { IntellitoolxFormErrors } from "intellitoolx";
|
|
532
|
+
```
|
|
424
533
|
|
|
425
534
|
You can import it directly into any component.
|
|
426
535
|
|
|
427
|
-
|
|
536
|
+
### Basic Usage
|
|
428
537
|
|
|
429
|
-
|
|
430
|
-
<itx-form-errors [control]="emailControl"></itx-form-errors>
|
|
538
|
+
```html
|
|
539
|
+
<input [formControl]="emailControl" /> <itx-form-errors [control]="emailControl"></itx-form-errors>
|
|
540
|
+
```
|
|
431
541
|
|
|
432
542
|
Errors will display automatically when:
|
|
433
|
-
control is touched
|
|
434
|
-
control is invalid
|
|
435
543
|
|
|
436
|
-
|
|
544
|
+
- control is touched
|
|
545
|
+
- control is invalid
|
|
546
|
+
|
|
547
|
+
### Default Supported Errors
|
|
548
|
+
|
|
437
549
|
The component includes built-in messages for common validators:
|
|
438
550
|
|
|
439
|
-
Error Key Message
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
controlLabel="Amount"
|
|
459
|
-
|
|
460
|
-
> </itx-form-errors>
|
|
551
|
+
| Error Key | Message |
|
|
552
|
+
| ----------------------------- | ------------------------------------------ |
|
|
553
|
+
| required | This field is required |
|
|
554
|
+
| email | The email entered is invalid |
|
|
555
|
+
| minlength | You must enter at least X characters |
|
|
556
|
+
| maxlength | You must not enter more than X characters |
|
|
557
|
+
| pattern | Your entry must match the required pattern |
|
|
558
|
+
| passwordMismatch | Password and confirm password do not match |
|
|
559
|
+
| futureDate | Future date is not allowed |
|
|
560
|
+
| duplicateEmail | Each email must be unique |
|
|
561
|
+
| maxWords | Exceeded maximum number of words |
|
|
562
|
+
| maxMonthYear | Date is later than allowed |
|
|
563
|
+
| minMonthYear | Date is earlier than allowed |
|
|
564
|
+
| exceededAllowedDateDifference | Date difference can only be one month |
|
|
565
|
+
| exceededLeastDateAllowed | Start date cannot be greater than end date |
|
|
566
|
+
|
|
567
|
+
### Adding Control Labels (User-Friendly Messages)
|
|
568
|
+
|
|
569
|
+
```html
|
|
570
|
+
<itx-form-errors [control]="amountControl" controlLabel="Amount"> </itx-form-errors>
|
|
571
|
+
```
|
|
461
572
|
|
|
462
573
|
Example output:
|
|
463
574
|
Amount cannot be greater than 100
|
|
@@ -465,482 +576,570 @@ Amount cannot be greater than 100
|
|
|
465
576
|
Component-Level Custom Messages
|
|
466
577
|
Override messages for a specific field.
|
|
467
578
|
|
|
579
|
+
```ts
|
|
468
580
|
componentValidation = {
|
|
469
|
-
required: { message:
|
|
470
|
-
minlength: { message:
|
|
581
|
+
required: { message: "Email is mandatory" },
|
|
582
|
+
minlength: { message: "Too short" },
|
|
471
583
|
};
|
|
584
|
+
```
|
|
472
585
|
|
|
473
|
-
|
|
474
|
-
[control]="emailControl"
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
> </itx-form-errors>
|
|
586
|
+
```html
|
|
587
|
+
<itx-form-errors [control]="emailControl" [componentValidation]="componentValidation"> </itx-form-errors>
|
|
588
|
+
```
|
|
478
589
|
|
|
479
590
|
### Using Custom Validators with Messages
|
|
480
591
|
|
|
481
592
|
If your validator returns an object:
|
|
482
|
-
|
|
593
|
+
|
|
594
|
+
```ts
|
|
595
|
+
return { customMinValue: { message: "Value is too small" } };
|
|
596
|
+
```
|
|
483
597
|
|
|
484
598
|
The component will display:
|
|
485
599
|
Value is too small
|
|
486
600
|
|
|
487
|
-
|
|
601
|
+
### Extending Error Messages (Recommended)
|
|
488
602
|
|
|
489
603
|
Consumers can extend the component to add global or shared messages.
|
|
490
604
|
|
|
491
|
-
|
|
605
|
+
Option 1 — Extend the Component
|
|
492
606
|
|
|
493
607
|
Create your own reusable error component:
|
|
494
608
|
|
|
495
|
-
|
|
496
|
-
import {
|
|
609
|
+
```ts
|
|
610
|
+
import { Component } from "@angular/core";
|
|
611
|
+
import { IntellitoolxFormErrors } from "intellitoolx";
|
|
497
612
|
|
|
498
613
|
@Component({
|
|
499
|
-
selector:
|
|
500
|
-
standalone: true,
|
|
501
|
-
imports: [IntellitoolxFormErrors],
|
|
502
|
-
template: `
|
|
503
|
-
[control]="control"
|
|
504
|
-
[componentValidation]="componentValidation"
|
|
505
|
-
[controlLabel]="controlLabel"
|
|
506
|
-
/>
|
|
507
|
-
`,
|
|
614
|
+
selector: "app-form-errors",
|
|
615
|
+
standalone: true,
|
|
616
|
+
imports: [IntellitoolxFormErrors],
|
|
617
|
+
template: ` <itx-form-errors [control]="control" [componentValidation]="componentValidation" [controlLabel]="controlLabel" /> `,
|
|
508
618
|
})
|
|
509
619
|
export class AppFormErrors extends IntellitoolxFormErrors {
|
|
510
|
-
override errorMessages = {
|
|
511
|
-
...this.errorMessages,
|
|
512
|
-
required:
|
|
513
|
-
phone:
|
|
514
|
-
usernameTaken:
|
|
515
|
-
};
|
|
620
|
+
override errorMessages = {
|
|
621
|
+
...this.errorMessages,
|
|
622
|
+
required: "This field cannot be empty",
|
|
623
|
+
phone: "Phone number is invalid",
|
|
624
|
+
usernameTaken: "This username is already taken",
|
|
625
|
+
};
|
|
516
626
|
}
|
|
627
|
+
```
|
|
517
628
|
|
|
518
629
|
Now use:
|
|
630
|
+
|
|
631
|
+
```html
|
|
519
632
|
<app-form-errors [control]="control"></app-form-errors>
|
|
633
|
+
```
|
|
520
634
|
|
|
521
|
-
|
|
635
|
+
Option 2 — Extend via Custom Validator Keys
|
|
522
636
|
|
|
523
637
|
Return new error keys from validators:
|
|
524
638
|
|
|
639
|
+
```ts
|
|
525
640
|
return { usernameTaken: true };
|
|
641
|
+
```
|
|
526
642
|
|
|
527
643
|
Then provide the message:
|
|
528
644
|
|
|
645
|
+
```ts
|
|
529
646
|
componentValidation = {
|
|
530
|
-
usernameTaken: { message:
|
|
647
|
+
usernameTaken: { message: "Username already exists" },
|
|
531
648
|
};
|
|
649
|
+
```
|
|
532
650
|
|
|
533
|
-
|
|
651
|
+
Option 3 — Global Shared Messages Service (Advanced)
|
|
534
652
|
|
|
535
653
|
Create a shared constant:
|
|
536
654
|
|
|
655
|
+
```ts
|
|
537
656
|
export const APP_ERROR_MESSAGES = {
|
|
538
|
-
required:
|
|
539
|
-
email:
|
|
657
|
+
required: "Required field",
|
|
658
|
+
email: "Invalid email address",
|
|
540
659
|
};
|
|
660
|
+
```
|
|
541
661
|
|
|
542
662
|
Then extend:
|
|
663
|
+
|
|
664
|
+
```ts
|
|
543
665
|
override errorMessages = {
|
|
544
666
|
...APP_ERROR_MESSAGES,
|
|
545
667
|
};
|
|
668
|
+
```
|
|
546
669
|
|
|
547
|
-
|
|
670
|
+
### Supported Error Value Types
|
|
548
671
|
|
|
549
672
|
The component intelligently handles different validator outputs:
|
|
550
|
-
Boolean { required: true } → uses default or custom message
|
|
551
|
-
String { customError: 'Invalid value provided' } → displays string directly
|
|
552
|
-
Object { minlength: { requiredLength: 5 } } → dynamic message rendering
|
|
553
673
|
|
|
554
|
-
|
|
674
|
+
- Boolean { required: true } → uses default or custom message
|
|
675
|
+
- String { customError: 'Invalid value provided' } → displays string directly
|
|
676
|
+
- Object { minlength: { requiredLength: 5 } } → dynamic message rendering
|
|
677
|
+
|
|
678
|
+
Built-in Smart Messages
|
|
555
679
|
|
|
556
|
-
Pattern Errors
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
Min / Max Validators
|
|
560
|
-
Age cannot be less than 18
|
|
561
|
-
Price cannot be greater than 100
|
|
562
|
-
Ngb Date Errors
|
|
563
|
-
Invalid date format provided
|
|
680
|
+
- Pattern Errors Display: `Please provide a valid {controlLabel}`
|
|
681
|
+
- Min / Max Validators Display: `Age cannot be less than 18` / `Price cannot be greater than 100`
|
|
682
|
+
- Ngb Date Errors Display: `Invalid date format provided`
|
|
564
683
|
|
|
565
|
-
|
|
684
|
+
Best Practices
|
|
566
685
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
686
|
+
- Always provide controlLabel for better UX
|
|
687
|
+
- Use componentValidation for field-specific overrides
|
|
688
|
+
- Extend the component for app-wide consistency
|
|
689
|
+
- Return structured error objects from custom validators
|
|
690
|
+
- Keep error keys consistent across the application
|
|
572
691
|
|
|
573
692
|
### Example (Full Integration)
|
|
574
693
|
|
|
694
|
+
```html
|
|
575
695
|
<input formControlName="email" />
|
|
576
696
|
|
|
577
|
-
<app-form-errors
|
|
578
|
-
|
|
579
|
-
controlLabel="Email Address"
|
|
580
|
-
|
|
581
|
-
> </app-form-errors>
|
|
697
|
+
<app-form-errors [control]="form.controls.email" controlLabel="Email Address"> </app-form-errors>
|
|
698
|
+
```
|
|
582
699
|
|
|
583
700
|
# RequiredMarkerDirective
|
|
584
701
|
|
|
585
702
|
An Angular standalone directive that automatically adds a visual required marker to form labels when the associated form control has a required validator.
|
|
586
703
|
This ensures consistent UX and eliminates manual asterisk management.
|
|
587
704
|
|
|
588
|
-
|
|
705
|
+
### Import
|
|
589
706
|
|
|
590
|
-
|
|
707
|
+
```ts
|
|
708
|
+
import { RequiredMarkerDirective } from "intellitoolx";
|
|
709
|
+
```
|
|
591
710
|
|
|
592
711
|
Because it is standalone, import it directly:
|
|
593
712
|
|
|
713
|
+
```ts
|
|
594
714
|
@Component({
|
|
595
|
-
standalone: true,
|
|
596
|
-
imports: [RequiredMarkerDirective],
|
|
715
|
+
standalone: true,
|
|
716
|
+
imports: [RequiredMarkerDirective],
|
|
597
717
|
})
|
|
718
|
+
```
|
|
598
719
|
|
|
599
|
-
|
|
720
|
+
### Basic Usage
|
|
600
721
|
|
|
601
722
|
Add the directive to a <label> element.
|
|
602
723
|
|
|
724
|
+
```html
|
|
603
725
|
<label for="email" itxRequired>Email</label>
|
|
726
|
+
|
|
604
727
|
<input id="email" formControlName="email" />
|
|
728
|
+
```
|
|
605
729
|
|
|
606
730
|
If the control has Validators.required, the output becomes:
|
|
607
|
-
Email
|
|
731
|
+
Email\*
|
|
608
732
|
|
|
609
|
-
|
|
733
|
+
### How It Works
|
|
610
734
|
|
|
611
|
-
Reads the label’s for attribute.
|
|
612
|
-
Finds the matching control inside the parent FormGroup.
|
|
613
|
-
Checks for Validators.required.
|
|
614
|
-
Adds or removes the required marker dynamically.
|
|
615
|
-
Updates when value or status changes.
|
|
616
|
-
|
|
617
|
-
## Dynamic Updates
|
|
735
|
+
- Reads the label’s for attribute.
|
|
736
|
+
- Finds the matching control inside the parent FormGroup.
|
|
737
|
+
- Checks for Validators.required.
|
|
738
|
+
- Adds or removes the required marker dynamically.
|
|
739
|
+
- Updates when value or status changes.
|
|
618
740
|
|
|
741
|
+
Dynamic Updates
|
|
619
742
|
If required validation is added or removed at runtime:
|
|
743
|
+
|
|
744
|
+
```ts
|
|
620
745
|
control.setValidators([Validators.required]);
|
|
621
746
|
control.updateValueAndValidity();
|
|
747
|
+
```
|
|
748
|
+
|
|
622
749
|
The label updates automatically.
|
|
623
750
|
|
|
624
|
-
|
|
751
|
+
### Default Marker Behavior
|
|
625
752
|
|
|
626
|
-
Property Default
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
753
|
+
| Property | Default |
|
|
754
|
+
| -------------------- | ------- |
|
|
755
|
+
| marker sign | \* |
|
|
756
|
+
| color | red |
|
|
757
|
+
| spacing | 0.25rem |
|
|
758
|
+
| position after label | text |
|
|
632
759
|
|
|
633
|
-
|
|
760
|
+
### Global Configuration
|
|
634
761
|
|
|
762
|
+
You can configure marker appearance globally using the provided injection token.
|
|
635
763
|
Step 1 — Provide Configuration
|
|
636
|
-
|
|
764
|
+
|
|
765
|
+
```ts
|
|
766
|
+
import { REQUIRED_MARKER_GLOBAL_CONFIG } from "intellitoolx";
|
|
637
767
|
|
|
638
768
|
providers: [
|
|
639
|
-
{
|
|
640
|
-
provide: REQUIRED_MARKER_GLOBAL_CONFIG,
|
|
641
|
-
useValue: {
|
|
642
|
-
sign:
|
|
643
|
-
color:
|
|
644
|
-
spacing:
|
|
645
|
-
position:
|
|
646
|
-
},
|
|
647
|
-
},
|
|
769
|
+
{
|
|
770
|
+
provide: REQUIRED_MARKER_GLOBAL_CONFIG,
|
|
771
|
+
useValue: {
|
|
772
|
+
sign: "*",
|
|
773
|
+
color: "#d9534f",
|
|
774
|
+
spacing: "4px",
|
|
775
|
+
position: "after", // 'before' | 'after'
|
|
776
|
+
},
|
|
777
|
+
},
|
|
648
778
|
];
|
|
779
|
+
```
|
|
649
780
|
|
|
650
781
|
Configuration Options
|
|
782
|
+
|
|
783
|
+
```ts
|
|
651
784
|
export interface ResolvedRequiredMarkerConfig {
|
|
652
|
-
sign: string;
|
|
653
|
-
color: string;
|
|
654
|
-
spacing: string;
|
|
655
|
-
position:
|
|
785
|
+
sign: string;
|
|
786
|
+
color: string;
|
|
787
|
+
spacing: string;
|
|
788
|
+
position: "before" | "after";
|
|
656
789
|
}
|
|
790
|
+
```
|
|
657
791
|
|
|
658
792
|
Positioning the Marker
|
|
659
|
-
After (default)
|
|
660
|
-
Email
|
|
661
|
-
Before
|
|
662
|
-
position: 'before'
|
|
663
|
-
|
|
664
|
-
- Email
|
|
793
|
+
After (default) `Email \*`
|
|
794
|
+
Before position: 'before' `\* Email`
|
|
665
795
|
|
|
666
796
|
Preserves Additional Label Text
|
|
667
797
|
The directive preserves text in parentheses or suffix content.
|
|
798
|
+
|
|
799
|
+
```html
|
|
668
800
|
<label for="dob" itxRequired>Date of Birth (optional)</label>
|
|
801
|
+
```
|
|
669
802
|
|
|
670
|
-
Output when required:
|
|
671
|
-
Date of Birth \* (optional)
|
|
803
|
+
Output when required: `Date of Birth \* (optional)`
|
|
672
804
|
Works With Nested Form Groups
|
|
673
|
-
Ensure the for attribute matches the control name.
|
|
805
|
+
Ensure the `for` attribute matches the control name.
|
|
806
|
+
|
|
807
|
+
```html
|
|
674
808
|
<label for="address.street" itxRequired>Street</label>
|
|
809
|
+
|
|
675
810
|
<input formControlName="street" />
|
|
811
|
+
```
|
|
676
812
|
|
|
677
|
-
|
|
813
|
+
### Requirements
|
|
678
814
|
|
|
679
|
-
Must be used inside a form with FormGroupDirective
|
|
680
|
-
Label for attribute must match control name
|
|
815
|
+
- Must be used inside a form with FormGroupDirective
|
|
816
|
+
- Label for attribute must match control name
|
|
681
817
|
|
|
682
|
-
|
|
818
|
+
### Common Mistakes
|
|
683
819
|
|
|
684
|
-
Missing for attribute
|
|
685
|
-
Label not associated with control
|
|
686
|
-
Control name mismatch
|
|
820
|
+
- Missing for attribute
|
|
821
|
+
- Label not associated with control
|
|
822
|
+
- Control name mismatch
|
|
687
823
|
|
|
688
824
|
Example (Complete)
|
|
689
825
|
|
|
826
|
+
```html
|
|
690
827
|
<form [formGroup]="form">
|
|
691
828
|
<label for="email" itxRequired>Email</label>
|
|
692
829
|
<input id="email" formControlName="email" />
|
|
693
830
|
</form>
|
|
694
|
-
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
```ts
|
|
834
|
+
email: new FormControl("", Validators.required);
|
|
835
|
+
```
|
|
695
836
|
|
|
696
837
|
# JsonParsePipe
|
|
697
838
|
|
|
698
839
|
An Angular standalone pipe that safely parses JSON strings into JavaScript objects.
|
|
840
|
+
Built on top of `IntelliToolxHelper.convertJsonStringToJson`, this pipe prevents template errors when dealing with dynamic or stringified JSON data.
|
|
699
841
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
## Import
|
|
842
|
+
### Import
|
|
703
843
|
|
|
704
|
-
|
|
844
|
+
```ts
|
|
845
|
+
import { JsonParsePipe } from "intellitoolx";
|
|
846
|
+
```
|
|
705
847
|
|
|
706
848
|
Because it is standalone, import it directly:
|
|
707
849
|
|
|
850
|
+
```ts
|
|
708
851
|
@Component({
|
|
709
|
-
standalone: true,
|
|
710
|
-
imports: [JsonParsePipe],
|
|
852
|
+
standalone: true,
|
|
853
|
+
imports: [JsonParsePipe],
|
|
711
854
|
})
|
|
855
|
+
```
|
|
712
856
|
|
|
713
|
-
|
|
857
|
+
### Usage
|
|
714
858
|
|
|
715
859
|
Basic Example
|
|
860
|
+
|
|
861
|
+
```
|
|
716
862
|
{{ jsonString | jsonParse | json }}
|
|
863
|
+
```
|
|
717
864
|
|
|
718
865
|
Input
|
|
866
|
+
|
|
867
|
+
```ts
|
|
719
868
|
jsonString = '{"name":"John","age":30}';
|
|
869
|
+
```
|
|
720
870
|
|
|
721
871
|
Output
|
|
872
|
+
|
|
873
|
+
```json
|
|
722
874
|
{
|
|
723
|
-
"name": "John",
|
|
724
|
-
"age": 30
|
|
875
|
+
"name": "John",
|
|
876
|
+
"age": 30
|
|
725
877
|
}
|
|
878
|
+
```
|
|
726
879
|
|
|
727
|
-
|
|
880
|
+
### When to Use
|
|
728
881
|
|
|
729
882
|
Use jsonParse when:
|
|
730
|
-
API responses contain stringified JSON
|
|
731
|
-
Form values store serialized objects
|
|
732
|
-
LocalStorage data needs parsing
|
|
733
|
-
Preventing template crashes from invalid JSON
|
|
734
883
|
|
|
735
|
-
|
|
884
|
+
- API responses contain stringified JSON
|
|
885
|
+
- Form values store serialized objects
|
|
886
|
+
- LocalStorage data needs parsing
|
|
887
|
+
- Preventing template crashes from invalid JSON
|
|
888
|
+
|
|
889
|
+
### Behavior
|
|
736
890
|
|
|
737
891
|
The pipe safely handles multiple input types:
|
|
738
892
|
|
|
739
|
-
Input Result
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
893
|
+
| Input | Result |
|
|
894
|
+
| ------------------------ | --------- |
|
|
895
|
+
| Valid JSON string Parsed | object |
|
|
896
|
+
| Invalid JSON string | null |
|
|
897
|
+
| Object Returned | unchanged |
|
|
898
|
+
| null / undefined | null |
|
|
744
899
|
|
|
745
900
|
Examples
|
|
746
901
|
Parse API Data
|
|
747
902
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
903
|
+
```html
|
|
904
|
+
<div *ngIf="user.data | jsonParse as parsed">{{ parsed.name }}</div>
|
|
905
|
+
```
|
|
751
906
|
|
|
752
907
|
Parse Stored JSON
|
|
908
|
+
|
|
909
|
+
```
|
|
753
910
|
{{ localStorageValue | jsonParse | json }}
|
|
911
|
+
```
|
|
754
912
|
|
|
755
913
|
Safe Access with Optional Chaining
|
|
914
|
+
|
|
915
|
+
```
|
|
756
916
|
{{ (settings | jsonParse)?.theme }}
|
|
917
|
+
```
|
|
757
918
|
|
|
758
919
|
Equivalent TypeScript Logic
|
|
759
920
|
|
|
760
921
|
The pipe internally performs:
|
|
922
|
+
|
|
923
|
+
```ts
|
|
761
924
|
IntelliToolxHelper.convertJsonStringToJson(value);
|
|
925
|
+
```
|
|
762
926
|
|
|
763
927
|
Error Safety
|
|
928
|
+
|
|
764
929
|
Unlike JSON.parse() directly in templates, this pipe:
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
930
|
+
|
|
931
|
+
- prevents runtime template errors
|
|
932
|
+
- avoids breaking change detection
|
|
933
|
+
- returns null on parsing failure
|
|
768
934
|
|
|
769
935
|
For large datasets or repeated bindings:
|
|
770
936
|
Prefer parsing in the component
|
|
937
|
+
|
|
938
|
+
```ts
|
|
771
939
|
parsedData = IntelliToolxHelper.convertJsonStringToJson(data);
|
|
940
|
+
```
|
|
772
941
|
|
|
773
942
|
# IntelliToolx Validators
|
|
774
943
|
|
|
775
944
|
A set of reusable Angular Reactive Form validators designed for common business rules such as amount limits, password matching, word limits, and duplicate detection.
|
|
776
|
-
|
|
777
|
-
These validators integrate seamlessly with Angular forms and work perfectly with IntellitoolxFormErrors for displaying user-friendly messages.
|
|
945
|
+
These validators integrate seamlessly with Angular forms and work perfectly with `IntellitoolxFormErrors` for displaying user-friendly messages.
|
|
778
946
|
|
|
779
947
|
Import
|
|
780
|
-
import {
|
|
781
|
-
customMaxAmountValidator,
|
|
782
|
-
customMinAmountValidator,
|
|
783
|
-
MaxWordsValidator,
|
|
784
|
-
PasswordMismatchValidator,
|
|
785
|
-
uniqueEmailsValidator
|
|
786
|
-
} from 'intellitoolx-helper';
|
|
787
948
|
|
|
788
|
-
|
|
949
|
+
```ts
|
|
950
|
+
import { customMaxAmountValidator, customMinAmountValidator, maxWordsValidator, passwordMismatchValidator, uniqueEmailsValidator } from "intellitoolx";
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
### Validators Overview
|
|
789
954
|
|
|
790
|
-
Validator Purpose
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
955
|
+
| Validator | Purpose |
|
|
956
|
+
| ------------------------- | -------------------------------------- |
|
|
957
|
+
| customMaxAmountValidator | Enforces maximum numeric value |
|
|
958
|
+
| customMinAmountValidator | Enforces minimum numeric value |
|
|
959
|
+
| maxWordsValidator | Limits number of words |
|
|
960
|
+
| passwordMismatchValidator | Ensures password fields match |
|
|
961
|
+
| uniqueEmailsValidator | Prevents duplicate emails in FormArray |
|
|
796
962
|
|
|
797
|
-
|
|
963
|
+
### customMaxAmountValidator(maxValue)
|
|
798
964
|
|
|
799
965
|
Ensures a numeric value does not exceed a specified maximum.
|
|
966
|
+
|
|
967
|
+
```ts
|
|
800
968
|
customMaxAmountValidator(maxValue: number): ValidatorFn
|
|
969
|
+
```
|
|
801
970
|
|
|
802
971
|
Example
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
]);
|
|
972
|
+
|
|
973
|
+
```ts
|
|
974
|
+
amount = new FormControl("", [customMaxAmountValidator(1000)]);
|
|
975
|
+
```
|
|
806
976
|
|
|
807
977
|
Error Output
|
|
978
|
+
|
|
979
|
+
```json
|
|
808
980
|
{
|
|
809
|
-
customMaxValue: {
|
|
810
|
-
requiredMin: 1000,
|
|
811
|
-
actual: 1200,
|
|
812
|
-
message: "The value must not exceed 1000.00"
|
|
813
|
-
}
|
|
981
|
+
"customMaxValue": {
|
|
982
|
+
"requiredMin": 1000,
|
|
983
|
+
"actual": 1200,
|
|
984
|
+
"message": "The value must not exceed 1000.00"
|
|
985
|
+
}
|
|
814
986
|
}
|
|
987
|
+
```
|
|
815
988
|
|
|
816
989
|
Notes
|
|
817
|
-
Accepts numeric values only
|
|
818
|
-
Returns a formatted error message
|
|
819
|
-
Works with IntellitoolxFormErrors automatically
|
|
820
990
|
|
|
821
|
-
|
|
991
|
+
- Accepts numeric values only
|
|
992
|
+
- Returns a formatted error message
|
|
993
|
+
- Works with IntellitoolxFormErrors automatically
|
|
994
|
+
|
|
995
|
+
### customMinAmountValidator(minValue)
|
|
822
996
|
|
|
823
997
|
Ensures a numeric value is at least the specified minimum.
|
|
998
|
+
|
|
999
|
+
```ts
|
|
824
1000
|
customMinAmountValidator(minValue: number): ValidatorFn
|
|
1001
|
+
```
|
|
825
1002
|
|
|
826
1003
|
Example
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
]);
|
|
1004
|
+
|
|
1005
|
+
```ts
|
|
1006
|
+
amount = new FormControl("", [customMinAmountValidator(10)]);
|
|
1007
|
+
```
|
|
1008
|
+
|
|
830
1009
|
Error Output
|
|
1010
|
+
|
|
1011
|
+
```json
|
|
831
1012
|
{
|
|
832
|
-
customMinValue: {
|
|
833
|
-
requiredMin: 10,
|
|
834
|
-
actual: 5,
|
|
835
|
-
message: "The value must be at least 10.00"
|
|
836
|
-
}
|
|
1013
|
+
"customMinValue": {
|
|
1014
|
+
"requiredMin": 10,
|
|
1015
|
+
"actual": 5,
|
|
1016
|
+
"message": "The value must be at least 10.00"
|
|
1017
|
+
}
|
|
837
1018
|
}
|
|
1019
|
+
```
|
|
838
1020
|
|
|
839
|
-
|
|
1021
|
+
### maxWordsValidator(maxWords)
|
|
840
1022
|
|
|
841
1023
|
Limits the number of words in a text input.
|
|
842
|
-
|
|
1024
|
+
maxWordsValidator(maxWords: number): ValidatorFn
|
|
843
1025
|
|
|
844
1026
|
Example
|
|
845
|
-
description = new FormControl('', [
|
|
846
|
-
MaxWordsValidator(20)
|
|
847
|
-
]);
|
|
848
1027
|
|
|
849
|
-
|
|
1028
|
+
```ts
|
|
1029
|
+
description = new FormControl("", [maxWordsValidator(20)]);
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
Behavior
|
|
850
1033
|
|
|
851
|
-
Ignores extra whitespace
|
|
852
|
-
Counts words separated by spaces
|
|
1034
|
+
- Ignores extra whitespace
|
|
1035
|
+
- Counts words separated by spaces
|
|
853
1036
|
|
|
854
1037
|
Error Output
|
|
1038
|
+
|
|
1039
|
+
```json
|
|
855
1040
|
{
|
|
856
|
-
maxWords: {
|
|
857
|
-
actual: 25,
|
|
858
|
-
max: 20
|
|
859
|
-
}
|
|
1041
|
+
"maxWords": {
|
|
1042
|
+
"actual": 25,
|
|
1043
|
+
"max": 20
|
|
1044
|
+
}
|
|
860
1045
|
}
|
|
1046
|
+
```
|
|
861
1047
|
|
|
862
|
-
|
|
1048
|
+
### passwordMismatchValidator(controlName, matchingControlName)
|
|
863
1049
|
|
|
864
1050
|
Validates that two form fields match (commonly used for password confirmation).
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
1051
|
+
|
|
1052
|
+
```ts
|
|
1053
|
+
passwordMismatchValidator(
|
|
1054
|
+
controlName: string,
|
|
1055
|
+
matchingControlName: string
|
|
868
1056
|
)
|
|
1057
|
+
```
|
|
869
1058
|
|
|
870
1059
|
Example
|
|
1060
|
+
|
|
1061
|
+
```ts
|
|
871
1062
|
this.form = new FormGroup(
|
|
872
|
-
{
|
|
873
|
-
password: new FormControl(
|
|
874
|
-
confirmPassword: new FormControl(
|
|
875
|
-
},
|
|
876
|
-
{
|
|
877
|
-
validators:
|
|
878
|
-
}
|
|
1063
|
+
{
|
|
1064
|
+
password: new FormControl(""),
|
|
1065
|
+
confirmPassword: new FormControl(""),
|
|
1066
|
+
},
|
|
1067
|
+
{
|
|
1068
|
+
validators: passwordMismatchValidator("password", "confirmPassword"),
|
|
1069
|
+
},
|
|
879
1070
|
);
|
|
1071
|
+
```
|
|
880
1072
|
|
|
881
1073
|
Error Output
|
|
1074
|
+
|
|
1075
|
+
```
|
|
882
1076
|
{ passwordMismatch: true }
|
|
1077
|
+
```
|
|
883
1078
|
|
|
884
1079
|
Notes
|
|
885
|
-
Error is applied to the matching control
|
|
886
|
-
Ideal for password confirmation fields
|
|
887
1080
|
|
|
888
|
-
|
|
1081
|
+
- Error is applied to the matching control
|
|
1082
|
+
- Ideal for password confirmation fields
|
|
1083
|
+
|
|
1084
|
+
### uniqueEmailsValidator()
|
|
889
1085
|
|
|
890
1086
|
Ensures all email addresses inside a FormArray are unique.
|
|
1087
|
+
|
|
1088
|
+
```ts
|
|
891
1089
|
uniqueEmailsValidator(): ValidatorFn
|
|
1090
|
+
```
|
|
892
1091
|
|
|
893
1092
|
Example
|
|
1093
|
+
|
|
1094
|
+
```ts
|
|
894
1095
|
this.form = new FormGroup({
|
|
895
|
-
contacts: new FormArray([
|
|
896
|
-
new FormGroup({
|
|
897
|
-
email: new FormControl(
|
|
898
|
-
})
|
|
899
|
-
])
|
|
1096
|
+
contacts: new FormArray([
|
|
1097
|
+
new FormGroup({
|
|
1098
|
+
email: new FormControl(""),
|
|
1099
|
+
}),
|
|
1100
|
+
]),
|
|
900
1101
|
});
|
|
901
1102
|
|
|
902
1103
|
this.contacts.setValidators(uniqueEmailsValidator());
|
|
1104
|
+
```
|
|
903
1105
|
|
|
904
|
-
|
|
1106
|
+
Behavior
|
|
905
1107
|
|
|
906
|
-
Ignores case and whitespace
|
|
907
|
-
Flags duplicates automatically
|
|
908
|
-
Updates errors dynamically
|
|
1108
|
+
- Ignores case and whitespace
|
|
1109
|
+
- Flags duplicates automatically
|
|
1110
|
+
- Updates errors dynamically
|
|
909
1111
|
|
|
910
|
-
Error Output (control level)
|
|
911
|
-
{
|
|
912
|
-
Error Output (form array level)
|
|
913
|
-
{ duplicateEmails: true }
|
|
1112
|
+
Error Output (control level) `{ duplicateEmail: true }`
|
|
1113
|
+
Error Output (form array level) `{ duplicateEmails: true }`
|
|
914
1114
|
|
|
915
1115
|
### Integration with IntellitoolxFormErrors
|
|
916
1116
|
|
|
917
1117
|
These validators return error keys compatible with the error component:
|
|
918
|
-
Validator Error Key
|
|
919
|
-
customMaxAmountValidator customMaxValue
|
|
920
|
-
customMinAmountValidator customMinValue
|
|
921
|
-
MaxWordsValidator maxWords
|
|
922
|
-
PasswordMismatchValidator passwordMismatch
|
|
923
|
-
uniqueEmailsValidator duplicateEmail
|
|
924
1118
|
|
|
925
|
-
|
|
1119
|
+
| Validator Error | Key |
|
|
1120
|
+
| ------------------------- | ---------------- |
|
|
1121
|
+
| customMaxAmountValidator | customMaxValue |
|
|
1122
|
+
| customMinAmountValidator | customMinValue |
|
|
1123
|
+
| maxWordsValidator | maxWords |
|
|
1124
|
+
| passwordMismatchValidator | passwordMismatch |
|
|
1125
|
+
| uniqueEmailsValidator | duplicateEmail |
|
|
1126
|
+
|
|
1127
|
+
Best Practices
|
|
926
1128
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
1129
|
+
- Use with Reactive Forms only
|
|
1130
|
+
- Combine with required validators when necessary
|
|
1131
|
+
- Provide control labels for better error messages
|
|
1132
|
+
- Normalize numeric inputs before validation
|
|
1133
|
+
- Use FormArray validators for dynamic lists
|
|
932
1134
|
|
|
933
1135
|
### Complete Example
|
|
934
1136
|
|
|
1137
|
+
```ts
|
|
935
1138
|
this.form = new FormGroup({
|
|
936
|
-
amount: new FormControl(
|
|
937
|
-
|
|
938
|
-
customMaxAmountValidator(1000),
|
|
939
|
-
]),
|
|
940
|
-
description: new FormControl('', [
|
|
941
|
-
MaxWordsValidator(20)
|
|
942
|
-
]),
|
|
1139
|
+
amount: new FormControl("", [customMinAmountValidator(10), customMaxAmountValidator(1000)]),
|
|
1140
|
+
description: new FormControl("", [maxWordsValidator(20)]),
|
|
943
1141
|
});
|
|
1142
|
+
```
|
|
944
1143
|
|
|
945
1144
|
License
|
|
946
1145
|
MIT
|