@i-cell/ids-angular 0.1.0 → 0.1.2
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/fesm2022/i-cell-ids-angular-forms.mjs +106 -26
- package/fesm2022/i-cell-ids-angular-forms.mjs.map +1 -1
- package/fesm2022/i-cell-ids-angular-table.mjs +4 -4
- package/fesm2022/i-cell-ids-angular-table.mjs.map +1 -1
- package/forms/components/input/input.directive.d.ts +1 -1
- package/forms/components/message/error-message/error-definition.directive.d.ts +49 -0
- package/forms/components/message/error-message/error-message.component.d.ts +11 -6
- package/forms/components/message/types/error-message-mapping.d.ts +9 -0
- package/forms/public-api.d.ts +2 -0
- package/package.json +11 -9
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, signal, Component, ViewEncapsulation, ChangeDetectionStrategy, InjectionToken, Directive, input, contentChildren, computed, Input, inject,
|
|
2
|
+
import { Injectable, signal, Component, ViewEncapsulation, ChangeDetectionStrategy, InjectionToken, Directive, input, contentChildren, computed, Input, inject, ElementRef, ChangeDetectorRef, viewChild, contentChild, isDevMode, effect, output } from '@angular/core';
|
|
3
3
|
import { ComponentBase, IdsSize, ComponentBaseWithDefaults, coerceBooleanAttribute } from '@i-cell/ids-angular/core';
|
|
4
|
-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
5
|
import { IdsIconComponent } from '@i-cell/ids-angular/icon';
|
|
6
|
-
import {
|
|
6
|
+
import { tap, map, of, switchMap, Subject } from 'rxjs';
|
|
7
7
|
import { Validators, FormGroupDirective, NgForm, NgControl } from '@angular/forms';
|
|
8
8
|
import { hasModifierKey } from '@angular/cdk/keycodes';
|
|
9
9
|
|
|
@@ -246,6 +246,71 @@ function requiredFalseValidator(control) {
|
|
|
246
246
|
return control.value === false ? null : { requiredFalse: true };
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Directive to map an error message to an error code for a form field.
|
|
251
|
+
* Mappings must be defined between the directive element's tags ordered by priority (descending from top to bottom).
|
|
252
|
+
* The error code is provided as an attribute, while the error message will be this directive's text content.
|
|
253
|
+
* The latter can be a plain string literal or even an interpolated string value.
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```html
|
|
257
|
+
* <ids-form-field>
|
|
258
|
+
* <ids-label>Input field</ids-label>
|
|
259
|
+
* <input
|
|
260
|
+
* idsInput
|
|
261
|
+
* ngModel
|
|
262
|
+
* customValidator
|
|
263
|
+
* required
|
|
264
|
+
* [minlength]="3"
|
|
265
|
+
* [maxlength]="10"
|
|
266
|
+
* [pattern]="validPattern"
|
|
267
|
+
* >
|
|
268
|
+
* <ids-error-message>
|
|
269
|
+
* <ids-error-def code="required">{{ 'ERROR.REQUIRED.CUSTOM' | translate }}</ids-error-def>
|
|
270
|
+
* <ids-error-def code="minlength">'minLength' error message</ids-error-def>
|
|
271
|
+
* <ids-error-def code="maxlength">'maxLength' error message</ids-error-def>
|
|
272
|
+
* <ids-error-def code="pattern">'pattern' error message with interpolation: {{ model.value }}</ids-error-def>
|
|
273
|
+
* <ids-error-def code="custom">Custom validator error message</ids-error-def>
|
|
274
|
+
* </ids-error-message>
|
|
275
|
+
* </ids-form-field>
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
class IdsErrorDefinitionDirective {
|
|
279
|
+
constructor() {
|
|
280
|
+
/**
|
|
281
|
+
* The validation error's identifier code
|
|
282
|
+
*/
|
|
283
|
+
this.code = input.required();
|
|
284
|
+
this._elementRef = inject(ElementRef);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* The validation error's message that will be presented to the user
|
|
288
|
+
*/
|
|
289
|
+
get errorMessage() {
|
|
290
|
+
return this._elementRef.nativeElement.innerText;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Creates a IdsErrorMessageMapping instance based on this directive's state (code, errorMessage)
|
|
294
|
+
* @returns A IdsErrorMessageMapping instance
|
|
295
|
+
*/
|
|
296
|
+
toErrorMessageMapping() {
|
|
297
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
298
|
+
const self = this;
|
|
299
|
+
return {
|
|
300
|
+
code: this.code(),
|
|
301
|
+
message: () => self.errorMessage,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.2", ngImport: i0, type: IdsErrorDefinitionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
305
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.1.2", type: IdsErrorDefinitionDirective, isStandalone: true, selector: "ids-error-def", inputs: { code: { classPropertyName: "code", publicName: "code", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 }); }
|
|
306
|
+
}
|
|
307
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.2", ngImport: i0, type: IdsErrorDefinitionDirective, decorators: [{
|
|
308
|
+
type: Directive,
|
|
309
|
+
args: [{
|
|
310
|
+
selector: 'ids-error-def',
|
|
311
|
+
}]
|
|
312
|
+
}] });
|
|
313
|
+
|
|
249
314
|
class IdsMessageSuffixDirective {
|
|
250
315
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.2", ngImport: i0, type: IdsMessageSuffixDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
251
316
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.2", type: IdsMessageSuffixDirective, isStandalone: true, selector: "[idsMessageSuffix]", ngImport: i0 }); }
|
|
@@ -310,32 +375,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.2", ngImpor
|
|
|
310
375
|
}] });
|
|
311
376
|
|
|
312
377
|
class IdsErrorMessageComponent extends ComponentBase {
|
|
378
|
+
get _hostName() {
|
|
379
|
+
return 'error-message';
|
|
380
|
+
}
|
|
313
381
|
constructor() {
|
|
314
|
-
super(
|
|
315
|
-
this.
|
|
316
|
-
this.
|
|
382
|
+
super();
|
|
383
|
+
this._parent = inject(IdsFormFieldComponent, { skipSelf: true });
|
|
384
|
+
this._control = signal(null);
|
|
385
|
+
this._errorDefDirs = contentChildren(IdsErrorDefinitionDirective);
|
|
386
|
+
this._errorDefs = computed(() => this._errorDefDirs().map((errorDefDir) => errorDefDir.toErrorMessageMapping()));
|
|
387
|
+
this._validationError = signal(null);
|
|
317
388
|
this._hostClasses = computed(() => this._getHostClasses([]));
|
|
318
389
|
this.suffixes = contentChildren(IdsMessageSuffixDirective);
|
|
390
|
+
toObservable(this._parent.control).pipe(tap((controlDir) => this._control.set(controlDir?.control ?? null)), map((controlDir) => controlDir?.statusChanges ?? of(null)), switchMap((statusChanges) => statusChanges), takeUntilDestroyed(this._destroyRef)).subscribe((status) => {
|
|
391
|
+
if (status === 'INVALID') {
|
|
392
|
+
const nextError = this._selectMostImportantValidationError();
|
|
393
|
+
this._validationError.set(nextError);
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
this._validationError.set(null);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
319
399
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (parent) {
|
|
326
|
-
const control = parent.control();
|
|
327
|
-
control?.statusChanges?.pipe(startWith(control.errors), takeUntilDestroyed(this._destroyRef)).subscribe(() => {
|
|
328
|
-
this._errors.set(control.errors);
|
|
329
|
-
});
|
|
400
|
+
_selectMostImportantValidationError() {
|
|
401
|
+
const errorDefs = this._errorDefs();
|
|
402
|
+
const control = this._control();
|
|
403
|
+
if (!errorDefs?.length || !control?.errors || Object.keys(control.errors).length === 0) {
|
|
404
|
+
return null;
|
|
330
405
|
}
|
|
406
|
+
const errorCodes = new Set(Object.keys(control.errors));
|
|
407
|
+
return errorDefs.find((errorDef) => errorCodes.has(errorDef.code)) ?? null;
|
|
331
408
|
}
|
|
332
|
-
|
|
333
|
-
|
|
409
|
+
_getValidationErrorMessage(messageOrFn) {
|
|
410
|
+
return messageOrFn instanceof Function ? messageOrFn() : messageOrFn;
|
|
411
|
+
}
|
|
412
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.2", ngImport: i0, type: IdsErrorMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
413
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.2", type: IdsErrorMessageComponent, isStandalone: true, selector: "ids-error-message", queries: [{ propertyName: "_errorDefDirs", predicate: IdsErrorDefinitionDirective, isSignal: true }, { propertyName: "suffixes", predicate: IdsMessageSuffixDirective, isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: IdsMessageDirective }], ngImport: i0, template: "<div class=\"ids-message__prefix\">\n <ng-content select=\"[idsMessagePrefix]\">\n <ids-icon aria-hidden=\"true\" fontIcon=\"exclamation-circle\" variant=\"error\" />\n </ng-content>\n</div>\n<div class=\"ids-message__text\">\n @let validationError = _validationError();\n @if (validationError) {\n @let messageString = _getValidationErrorMessage(validationError.message);\n {{ messageString }}\n }\n</div>\n@if (suffixes().length) {\n <div class=\"ids-message__suffix\">\n <ng-content select=\"[idsMessageSuffix]\" />\n </div>\n}\n", dependencies: [{ kind: "component", type: IdsIconComponent, selector: "ids-icon", inputs: ["size", "sizeCollection", "variant", "fontIcon", "svgIcon", "aria-hidden"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
334
414
|
}
|
|
335
415
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.2", ngImport: i0, type: IdsErrorMessageComponent, decorators: [{
|
|
336
416
|
type: Component,
|
|
337
|
-
args: [{ selector: 'ids-error-message', imports: [IdsIconComponent], hostDirectives: [IdsMessageDirective], encapsulation: ViewEncapsulation.None, template: "<div class=\"ids-message__prefix\">\n <ng-content select=\"[idsMessagePrefix]\">\n <ids-icon aria-hidden=\"true\" fontIcon=\"exclamation-circle\" />\n </ng-content>\n</div>\n<div class=\"ids-message__text\">\n
|
|
338
|
-
}] });
|
|
417
|
+
args: [{ selector: 'ids-error-message', imports: [IdsIconComponent], hostDirectives: [IdsMessageDirective], encapsulation: ViewEncapsulation.None, template: "<div class=\"ids-message__prefix\">\n <ng-content select=\"[idsMessagePrefix]\">\n <ids-icon aria-hidden=\"true\" fontIcon=\"exclamation-circle\" variant=\"error\" />\n </ng-content>\n</div>\n<div class=\"ids-message__text\">\n @let validationError = _validationError();\n @if (validationError) {\n @let messageString = _getValidationErrorMessage(validationError.message);\n {{ messageString }}\n }\n</div>\n@if (suffixes().length) {\n <div class=\"ids-message__suffix\">\n <ng-content select=\"[idsMessageSuffix]\" />\n </div>\n}\n" }]
|
|
418
|
+
}], ctorParameters: () => [] });
|
|
339
419
|
|
|
340
420
|
class IdsMessagePrefixDirective {
|
|
341
421
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.2", ngImport: i0, type: IdsMessagePrefixDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
@@ -382,11 +462,11 @@ class IdsSuccessMessageComponent extends ComponentBase {
|
|
|
382
462
|
return 'success-message';
|
|
383
463
|
}
|
|
384
464
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.2", ngImport: i0, type: IdsSuccessMessageComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
385
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.2", type: IdsSuccessMessageComponent, isStandalone: true, selector: "ids-success-message", queries: [{ propertyName: "suffixes", predicate: IdsMessageSuffixDirective, isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: IdsMessageDirective }], ngImport: i0, template: "<div class=\"ids-message__prefix\">\n <ng-content select=\"[idsMessagePrefix]\">\n <ids-icon aria-hidden=\"true\" fontIcon=\"check\" />\n </ng-content>\n</div>\n<div class=\"ids-message__text\">\n <ng-content />\n</div>\n@if (suffixes().length) {\n <div class=\"ids-message__suffix\">\n <ng-content select=\"[idsMessageSuffix]\" />\n </div>\n}\n", dependencies: [{ kind: "component", type: IdsIconComponent, selector: "ids-icon", inputs: ["size", "sizeCollection", "variant", "fontIcon", "svgIcon", "aria-hidden"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
465
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.2", type: IdsSuccessMessageComponent, isStandalone: true, selector: "ids-success-message", queries: [{ propertyName: "suffixes", predicate: IdsMessageSuffixDirective, isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: IdsMessageDirective }], ngImport: i0, template: "<div class=\"ids-message__prefix\">\n <ng-content select=\"[idsMessagePrefix]\">\n <ids-icon aria-hidden=\"true\" fontIcon=\"check\" variant=\"success\" />\n </ng-content>\n</div>\n<div class=\"ids-message__text\">\n <ng-content />\n</div>\n@if (suffixes().length) {\n <div class=\"ids-message__suffix\">\n <ng-content select=\"[idsMessageSuffix]\" />\n </div>\n}\n", dependencies: [{ kind: "component", type: IdsIconComponent, selector: "ids-icon", inputs: ["size", "sizeCollection", "variant", "fontIcon", "svgIcon", "aria-hidden"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
386
466
|
}
|
|
387
467
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.2", ngImport: i0, type: IdsSuccessMessageComponent, decorators: [{
|
|
388
468
|
type: Component,
|
|
389
|
-
args: [{ selector: 'ids-success-message', imports: [IdsIconComponent], hostDirectives: [IdsMessageDirective], encapsulation: ViewEncapsulation.None, template: "<div class=\"ids-message__prefix\">\n <ng-content select=\"[idsMessagePrefix]\">\n <ids-icon aria-hidden=\"true\" fontIcon=\"check\" />\n </ng-content>\n</div>\n<div class=\"ids-message__text\">\n <ng-content />\n</div>\n@if (suffixes().length) {\n <div class=\"ids-message__suffix\">\n <ng-content select=\"[idsMessageSuffix]\" />\n </div>\n}\n" }]
|
|
469
|
+
args: [{ selector: 'ids-success-message', imports: [IdsIconComponent], hostDirectives: [IdsMessageDirective], encapsulation: ViewEncapsulation.None, template: "<div class=\"ids-message__prefix\">\n <ng-content select=\"[idsMessagePrefix]\">\n <ids-icon aria-hidden=\"true\" fontIcon=\"check\" variant=\"success\" />\n </ng-content>\n</div>\n<div class=\"ids-message__text\">\n <ng-content />\n</div>\n@if (suffixes().length) {\n <div class=\"ids-message__suffix\">\n <ng-content select=\"[idsMessageSuffix]\" />\n </div>\n}\n" }]
|
|
390
470
|
}] });
|
|
391
471
|
|
|
392
472
|
const defaultConfig$1 = IDS_FORM_FIELD_DEFAULT_CONFIG_FACTORY();
|
|
@@ -509,7 +589,7 @@ class IdsInputDirective extends ComponentBaseWithDefaults {
|
|
|
509
589
|
this._defaultConfig = this._getDefaultConfig(defaultConfig, IDS_INPUT_DEFAULT_CONFIG);
|
|
510
590
|
this.errorStateChanges = new Subject();
|
|
511
591
|
this.successStateChanges = new Subject();
|
|
512
|
-
this.ngControl = inject(NgControl
|
|
592
|
+
this.ngControl = inject(NgControl);
|
|
513
593
|
this._focused = false;
|
|
514
594
|
this.placeholder = input('');
|
|
515
595
|
this.name = input();
|
|
@@ -556,12 +636,12 @@ class IdsInputDirective extends ComponentBaseWithDefaults {
|
|
|
556
636
|
}
|
|
557
637
|
_initErrorStateTracker() {
|
|
558
638
|
this._errorStateTracker = new ErrorStateTracker(this.errorStateMatcher(), this.ngControl, this._parentFormGroup, this._parentForm, this.errorStateChanges);
|
|
559
|
-
this.
|
|
639
|
+
this.errorStateChanges.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => this.hasErrorState.set(this._errorStateTracker.hasErrorState));
|
|
560
640
|
}
|
|
561
641
|
_setSuccessStateTracker(canHandleSuccessState) {
|
|
562
642
|
if (canHandleSuccessState) {
|
|
563
643
|
this._successStateTracker = new SuccessStateTracker(this.successStateMatcher(), this.ngControl, this._parentFormGroup, this._parentForm, this.successStateChanges);
|
|
564
|
-
this.successStateChanges.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => this.hasSuccessState.set(this._successStateTracker.hasSuccessState));
|
|
644
|
+
this._successStateSubscription = this.successStateChanges.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => this.hasSuccessState.set(this._successStateTracker.hasSuccessState));
|
|
565
645
|
}
|
|
566
646
|
else {
|
|
567
647
|
this._successStateTracker = undefined;
|
|
@@ -867,5 +947,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.2", ngImpor
|
|
|
867
947
|
* Generated bundle index. Do not edit.
|
|
868
948
|
*/
|
|
869
949
|
|
|
870
|
-
export { AbstractErrorStateMatcher, AbstractSuccessStateMatcher, ErrorStateMatcher, ErrorStateTracker, IDS_FIELDSET_DEFAULT_CONFIG, IDS_FIELDSET_DEFAULT_CONFIG_FACTORY, IDS_FORM_FIELD_CONTROL, IDS_FORM_FIELD_DEFAULT_CONFIG, IDS_FORM_FIELD_DEFAULT_CONFIG_FACTORY, IDS_INPUT_DEFAULT_CONFIG, IDS_INPUT_DEFAULT_CONFIG_FACTORY, IDS_MESSAGE_DEFAULT_CONFIG, IDS_MESSAGE_DEFAULT_CONFIG_FACTORY, IDS_OPTION_GROUP, IDS_OPTION_PARENT_COMPONENT, IDS_PSEUDO_CHECKBOX_PARENT, IdsErrorMessageComponent, IdsFieldsetComponent, IdsFieldsetMessageDirective, IdsFieldsetRowComponent, IdsFormFieldActionDirective, IdsFormFieldComponent, IdsFormFieldControl, IdsFormFieldVariant, IdsHintMessageComponent, IdsInputDirective, IdsLabelDirective, IdsMessageDirective, IdsMessagePrefixDirective, IdsMessageSuffixDirective, IdsMessageVariant, IdsOptionComponent, IdsOptionGroupComponent, IdsOptionSelectionChange, IdsPrefixDirective, IdsPseudoCheckboxState, IdsSuccessMessageComponent, IdsSuffixDirective, IdsValidators, Message, PseudoCheckboxComponent, SuccessStateMatcher, SuccessStateTracker, _countGroupLabelsBeforeOption, _getOptionScrollPosition, formFieldControlClass, requiredFalseValidator, requiredTrueValidator, requiredValidator };
|
|
950
|
+
export { AbstractErrorStateMatcher, AbstractSuccessStateMatcher, ErrorStateMatcher, ErrorStateTracker, IDS_FIELDSET_DEFAULT_CONFIG, IDS_FIELDSET_DEFAULT_CONFIG_FACTORY, IDS_FORM_FIELD_CONTROL, IDS_FORM_FIELD_DEFAULT_CONFIG, IDS_FORM_FIELD_DEFAULT_CONFIG_FACTORY, IDS_INPUT_DEFAULT_CONFIG, IDS_INPUT_DEFAULT_CONFIG_FACTORY, IDS_MESSAGE_DEFAULT_CONFIG, IDS_MESSAGE_DEFAULT_CONFIG_FACTORY, IDS_OPTION_GROUP, IDS_OPTION_PARENT_COMPONENT, IDS_PSEUDO_CHECKBOX_PARENT, IdsErrorDefinitionDirective, IdsErrorMessageComponent, IdsFieldsetComponent, IdsFieldsetMessageDirective, IdsFieldsetRowComponent, IdsFormFieldActionDirective, IdsFormFieldComponent, IdsFormFieldControl, IdsFormFieldVariant, IdsHintMessageComponent, IdsInputDirective, IdsLabelDirective, IdsMessageDirective, IdsMessagePrefixDirective, IdsMessageSuffixDirective, IdsMessageVariant, IdsOptionComponent, IdsOptionGroupComponent, IdsOptionSelectionChange, IdsPrefixDirective, IdsPseudoCheckboxState, IdsSuccessMessageComponent, IdsSuffixDirective, IdsValidators, Message, PseudoCheckboxComponent, SuccessStateMatcher, SuccessStateTracker, _countGroupLabelsBeforeOption, _getOptionScrollPosition, formFieldControlClass, requiredFalseValidator, requiredTrueValidator, requiredValidator };
|
|
871
951
|
//# sourceMappingURL=i-cell-ids-angular-forms.mjs.map
|